Как получить элемент по innerText

159

Как получить тег на html-странице, если я знаю, какой текстовый тег содержит. Например:

<a ...>SearchingText</a>
Антон Кандыбо
источник
1
чистый, функциональный подход, возвращающий массив stackoverflow.com/a/45089849/696535
Павел

Ответы:

155

Вам придется пройти вручную.

var aTags = document.getElementsByTagName("a");
var searchText = "SearchingText";
var found;

for (var i = 0; i < aTags.length; i++) {
  if (aTags[i].textContent == searchText) {
    found = aTags[i];
    break;
  }
}

// Use `found`.
Август Лиллеас
источник
1
@AutoSponge На самом деле innerHTML является стандартным. innerText не работает в FF
AnaMaria
Обновлен пример, textContent, вероятно, то, что вам нужно в этом случае. Спасибо, ребята :)
Август Лиллеас
1
@AugustLilleaas, что случилось с i < il? Что это делает?
Дэвид Сойер
1
Я обнаружил, что если у вас есть <span> <span> текст для поиска </span> </span>, этот метод может возвращать внешний диапазон вместо внутреннего.
Кевин Уиллер,
6
Нет, это вопрос о JavaScript и HTML, а не о Java
Август Лиллеас,
181

Вы можете использовать xpath для этого

var xpath = "//a[text()='SearchingText']";
var matchingElement = document.evaluate(xpath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;

Вы также можете искать элемент, содержащий некоторый текст, используя этот xpath:

var xpath = "//a[contains(text(),'Searching')]";
carlin.scott
источник
8
Это должен быть главный ответ. XPath может делать гораздо больше, например выбирать узел по значению атрибута, выбирать наборы узлов ... Простое введение: w3schools.com/xml/xpath_syntax.asp
Timathon
2
Вопрос в том, какова
потеря
2
@vsync Я думаю, что это будет быстрее, чем любой из других ответов, поскольку xpath выполняется алгоритмом, предоставленным браузером, а не выполняется в javascript, как все другие ответы здесь. Хотя это интересный вопрос.
carlin.scott 02
1
Похоже, Document.evaluate() это не
поддерживается
1
Я не знаю почему, но почему-то var xpath = "//a[text()='SearchingText']"; это не работает, но var xpath = "//a[contains(text(),'Searching')]"; это работает. Обратите внимание на исключенный символ, например \ '\'.
Джои Чо
39

Используя самый современный синтаксис, доступный на данный момент, это можно сделать очень чисто, вот так:

for (const a of document.querySelectorAll("a")) {
  if (a.textContent.includes("your search term")) {
    console.log(a.textContent)
  }
}

Или с отдельным фильтром:

[...document.querySelectorAll("a")]
   .filter(a => a.textContent.includes("your search term"))
   .forEach(a => console.log(a.textContent))

Естественно, устаревшие браузеры не справятся с этим, но вы можете использовать транспилятор, если требуется устаревшая поддержка.

user1106925
источник
<Подход с тремя фильтрами
Джон Вандивье
36

Вы можете использовать jQuery : contains () Selector

var element = $( "a:contains('SearchingText')" );
Mouneer
источник
Я получаю: Error: <![EX[["Tried to get element with id of \"%s\" but it is not present on the page","a:contains('SearchingText')"]]]> TAAL[1]хотя у меня есть элементы с "SearchingText" в них.
Ришаб Аграхари
15

Функциональный подход. Возвращает массив всех совпавших элементов и обрезает пробелы во время проверки.

function getElementsByText(str, tag = 'a') {
  return Array.prototype.slice.call(document.getElementsByTagName(tag)).filter(el => el.textContent.trim() === str.trim());
}

Применение

getElementsByText('Text here'); // second parameter is optional tag (default "a")

если вы просматриваете разные теги, например диапазон или кнопку

getElementsByText('Text here', 'span');
getElementsByText('Text here', 'button');

Значение по умолчанию tag = 'a' понадобится Babel для старых браузеров.

Павел
источник
Это неверно, потому что он также включает результаты для всех дочерних узлов. Т.е. если дочерний узел aбудет содержать str- elбудет включен в getElementsByTextрезультат; что неправильно.
avalanche1
@ avalanche1 это зависит от того, нежелательно ли это. Может потребоваться выделение по тексту, даже если он заключен в другой тег, например, <span> </span>
Павел
15

function findByTextContent(needle, haystack, precise) {
  // needle: String, the string to be found within the elements.
  // haystack: String, a selector to be passed to document.querySelectorAll(),
  //           NodeList, Array - to be iterated over within the function:
  // precise: Boolean, true - searches for that precise string, surrounded by
  //                          word-breaks,
  //                   false - searches for the string occurring anywhere
  var elems;

  // no haystack we quit here, to avoid having to search
  // the entire document:
  if (!haystack) {
    return false;
  }
  // if haystack is a string, we pass it to document.querySelectorAll(),
  // and turn the results into an Array:
  else if ('string' == typeof haystack) {
    elems = [].slice.call(document.querySelectorAll(haystack), 0);
  }
  // if haystack has a length property, we convert it to an Array
  // (if it's already an array, this is pointless, but not harmful):
  else if (haystack.length) {
    elems = [].slice.call(haystack, 0);
  }

  // work out whether we're looking at innerText (IE), or textContent 
  // (in most other browsers)
  var textProp = 'textContent' in document ? 'textContent' : 'innerText',
    // creating a regex depending on whether we want a precise match, or not:
    reg = precise === true ? new RegExp('\\b' + needle + '\\b') : new RegExp(needle),
    // iterating over the elems array:
    found = elems.filter(function(el) {
      // returning the elements in which the text is, or includes,
      // the needle to be found:
      return reg.test(el[textProp]);
    });
  return found.length ? found : false;;
}


findByTextContent('link', document.querySelectorAll('li'), false).forEach(function(elem) {
  elem.style.fontSize = '2em';
});

findByTextContent('link3', 'a').forEach(function(elem) {
  elem.style.color = '#f90';
});
<ul>
  <li><a href="#">link1</a>
  </li>
  <li><a href="#">link2</a>
  </li>
  <li><a href="#">link3</a>
  </li>
  <li><a href="#">link4</a>
  </li>
  <li><a href="#">link5</a>
  </li>
</ul>

Конечно, есть еще более простой способ:

var textProp = 'textContent' in document ? 'textContent' : 'innerText';

// directly converting the found 'a' elements into an Array,
// then iterating over that array with Array.prototype.forEach():
[].slice.call(document.querySelectorAll('a'), 0).forEach(function(aEl) {
  // if the text of the aEl Node contains the text 'link1':
  if (aEl[textProp].indexOf('link1') > -1) {
    // we update its style:
    aEl.style.fontSize = '2em';
    aEl.style.color = '#f90';
  }
});
<ul>
  <li><a href="#">link1</a>
  </li>
  <li><a href="#">link2</a>
  </li>
  <li><a href="#">link3</a>
  </li>
  <li><a href="#">link4</a>
  </li>
  <li><a href="#">link5</a>
  </li>
</ul>

Ссылки:

Дэвид просит восстановить Монику
источник
6

Просто передайте свою подстроку в следующую строку:

Внешний HTML

document.documentElement.outerHTML.includes('substring')

Внутренний HTML

document.documentElement.innerHTML.includes('substring')

Вы можете использовать их для поиска по всему документу и получения тегов, содержащих ваш поисковый запрос:

function get_elements_by_inner(word) {
    res = []
    elems = [...document.getElementsByTagName('a')];
    elems.forEach((elem) => { 
        if(elem.outerHTML.includes(word)) {
            res.push(elem)
        }
    })
    return(res)
}

Использование :

Сколько раз на этой странице упоминается пользователь "T3rm1"?

get_elements_by_inner("T3rm1").length

1

Сколько раз упоминается jQuery?

get_elements_by_inner("jQuery").length

3

Получите все элементы, содержащие слово "Cybernetic":

get_elements_by_inner("Cybernetic")

введите описание изображения здесь

Кибернетический
источник
Это возвращает истину или ложь, но не элемент.
T3rm1
Вы можете использовать условие истинности для перебора извлеченных элементов и извлечения всего, что вам нужно, из этих элементов. См. Обновленный ответ.
Cybernetic
4

Я обнаружил, что использование нового синтаксиса немного короче по сравнению с другими ответами. Итак, вот мое предложение:

const callback = element => element.innerHTML == 'My research'

const elements = Array.from(document.getElementsByTagName('a'))
// [a, a, a, ...]

const result = elements.filter(callback)

console.log(result)
// [a]

JSfiddle.net

Амин НАИРИ
источник
3

Чтобы получить метод фильтрации от пользователя 1106925, работающего в <= IE11, если необходимо

Вы можете заменить оператор распространения на:

[].slice.call(document.querySelectorAll("a"))

и включает вызов с a.textContent.match("your search term")

который работает довольно аккуратно:

[].slice.call(document.querySelectorAll("a"))
   .filter(a => a.textContent.match("your search term"))
   .forEach(a => console.log(a.textContent))
Алки
источник
Мне нравится этот метод. Вы также можете Array.fromвместо [].slice.call. Например: Array.from(document.querySelectorAll('a'))
Ричард
1

Хотя внутренний текст можно обойти, я думаю, что вы идете неверным путем. Эта внутренняя строка генерируется динамически? Если это так, вы можете присвоить тегу класс или, что еще лучше, идентификатор, когда текст будет там. Если статично, то еще проще.

Зак Маррапез
источник
1

Вы можете использовать a, TreeWalkerчтобы пройти по узлам DOM, найти все текстовые узлы, содержащие текст, и вернуть их родителей:

const findNodeByContent = (text, root = document.body) => {
  const treeWalker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT);

  const nodeList = [];

  while (treeWalker.nextNode()) {
    const node = treeWalker.currentNode;

    if (node.nodeType === Node.TEXT_NODE && node.textContent.includes(text)) {
      nodeList.push(node.parentNode);
    }
  };

  return nodeList;
}

const result = findNodeByContent('SearchingText');

console.log(result);
<a ...>SearchingText</a>

Ори Дрори
источник
1

Это делает свою работу.
Возвращает массив узлов, содержащих text.

function get_nodes_containing_text(selector, text) {
    const elements = [...document.querySelectorAll(selector)];

    return elements.filter(
      (element) =>
        element.childNodes[0]
        && element.childNodes[0].nodeValue
        && RegExp(text, "u").test(element.childNodes[0].nodeValue.trim())
    );
  }
лавина1
источник
0

Я думаю, чтобы мы вам помогли, вам нужно быть более конкретным.

  1. Как вы это находите? Javascript? PHP? Perl?
  2. Можете ли вы применить к тегу атрибут ID?

Если текст уникален (или действительно, если это не так, но вам придется пройти через массив), вы можете запустить регулярное выражение, чтобы найти его. Для этого подойдет использование PHP preg_match ().

Если вы используете Javascript и можете вставить атрибут ID, вы можете использовать getElementById ('id'). Затем вы можете получить доступ к атрибутам возвращенного элемента через DOM: https://developer.mozilla.org/en/DOM/element.1 .

Джефф Мейерс
источник
0

Мне просто нужен был способ получить элемент, содержащий определенный текст, и это то, что я придумал.

Используйте document.getElementsByInnerText()для получения нескольких элементов (несколько элементов могут иметь одинаковый точный текст) и используйте document.getElementByInnerText()для получения только одного элемента (первое совпадение).

Кроме того, вы можете локализовать поиск, используя элемент (например someElement.getElementByInnerText()) вместо document.

Возможно, вам придется настроить его, чтобы сделать его кроссбраузерным или удовлетворить ваши потребности.

Я думаю, что код не требует пояснений, поэтому я оставлю его как есть.

HTMLElement.prototype.getElementsByInnerText = function (text, escape) {
    var nodes  = this.querySelectorAll("*");
    var matches = [];
    for (var i = 0; i < nodes.length; i++) {
        if (nodes[i].innerText == text) {
            matches.push(nodes[i]);
        }
    }
    if (escape) {
        return matches;
    }
    var result = [];
    for (var i = 0; i < matches.length; i++) {
        var filter = matches[i].getElementsByInnerText(text, true);
        if (filter.length == 0) {
            result.push(matches[i]);
        }
    }
    return result;
};
document.getElementsByInnerText = HTMLElement.prototype.getElementsByInnerText;

HTMLElement.prototype.getElementByInnerText = function (text) {
    var result = this.getElementsByInnerText(text);
    if (result.length == 0) return null;
    return result[0];
}
document.getElementByInnerText = HTMLElement.prototype.getElementByInnerText;

console.log(document.getElementsByInnerText("Text1"));
console.log(document.getElementsByInnerText("Text2"));
console.log(document.getElementsByInnerText("Text4"));
console.log(document.getElementsByInnerText("Text6"));

console.log(document.getElementByInnerText("Text1"));
console.log(document.getElementByInnerText("Text2"));
console.log(document.getElementByInnerText("Text4"));
console.log(document.getElementByInnerText("Text6"));
<table>
    <tr>
        <td>Text1</td>
    </tr>
    <tr>
        <td>Text2</td>
    </tr>
    <tr>
        <td>
            <a href="#">Text2</a>
        </td>
    </tr>
    <tr>
        <td>
            <a href="#"><span>Text3</span></a>
        </td>
    </tr>
    <tr>
        <td>
            <a href="#">Special <span>Text4</span></a>
        </td>
    </tr>
    <tr>
        <td>
            Text5
            <a href="#">Text6</a>
            Text7
        </td>
    </tr>
</table>

акинури
источник