2009-10-05 3 views
301

Ищу селектор CSS для следующей таблицы:Есть ли селектор CSS для элементов, содержащих определенный текст?

Peter | male | 34 
Susanne | female | 12 

Есть ли селектор, чтобы соответствовать всем TDs, содержащие «мужской»?

+1

Проблема в том, что это было бы очень сложно реализовать по-настоящему. – Ms2ger

+2

Теперь я использую jQuery. Он работает отлично. – jantimon

+5

Селектор XPath может сделать это с помощью метода .text() (если вы не хотите использовать JavaScript-исполнитель). – djangofan

ответ

233

Если я правильно прочитал the specification, нет.

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

+153

Существует один краевой регистр: ': empty'. –

+2

Комментарий выше должен быть выбранным ответом! –

+9

Является ли этот ответ по-прежнему актуальным сегодня (2016 год)? –

3

Я боюсь, что это невозможно, потому что контент не является атрибутом и не доступен через псевдокласс. Полный список селекторов CSS3 можно найти в the CSS3 specification.

86

Вы должны были бы добавить атрибут данных в строках, называемых data-gender со значением male или female и использовать селектор атрибута:

HTML:

<td data-gender="male">...</td> 

CSS:

td[data-gender="male"] { ... } 
+3

Умное решение. Спасибо –

+1

Атрибуты данных не используются как JS-крючки или селектор CSS - для этого предназначены классы. Из спецификации: 'Атрибуты пользовательских данных предназначены для хранения конфиденциальных данных на странице или приложении, для которых нет более подходящих атрибутов или элементов.' Ссылка на спецификацию: [ссылка] (http: // www .w3.org/html/wg/drafts/html/master/dom.html # embedding-custom-non-visible-data-with-the-data - * - attributes) –

+10

@ Иван Дюрст, я искренне не согласен, как JS перехватчики или селектор CSS соответствуют определению данных, закрытым для страницы или приложения, и в настоящее время для гендерного пола не существует более подходящей html-семантики. Чем больше ответственности мы кладем на атрибут класса, тем дальше мы получаем от семантического html, поэтому я все для начала использования увеличенных метаданных, доступных нам в html5. – DannyMeister

98

Похоже, они думали об этом для спецификации CSS3 , но он не делал разреза.

:contains() селектор CSS3 http://www.w3.org/TR/css3-selectors/#content-selectors

+19

Последнее доступное определение': contains() 'можно найти здесь [http://www.w3.org/TR/2001/CR-css3-selectors-20011113/#content-selectors). – BoltClock

+2

'Похоже, что они думали об этом для спецификации CSS3, но не сделали разреза. И по уважительной причине это нарушило бы всю предпосылку разделения стиля, содержания, структуры и поведения. – Synetech

+26

@Synetech. Это может фактически помочь отделить стиль от контента, так как это означает, что контент не должен знать о его клиенте, который будет считаться важным для базового стиля. Прямо сейчас наш html-контент обычно тесно связан с css, включая классы, которые, как мы знаем, заботятся о стилистах. Они уже переходят к тому, чтобы позволить CSS на контенте, о чем свидетельствуют селекторы значений атрибутов в CSS3. – DannyMeister

128

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

$('td:contains("male")') 
+5

Заканчивается необходимость в этом противоположном: jQuery (element) .not (": contains ('string')") – Jazzy

+130

За исключением того, что это не CSS, это JavaScript. – Synetech

+5

Согласен - вот почему мой ответ сказал, что я использую jQuery, а не CSS. Но эта часть моего ответа была отредактирована. =) – moettinger

54

Существует на самом деле очень концептуальная основа, почему это не было реализовано. Это сочетание в основном 3-х аспектах:

  1. Текст содержание элемента фактически является потомком этого элемента
  2. Вы не можете настроить таргетинг на содержание текста непосредственно
  3. CSS не позволяет вознесения с селекторов

Эти 3 вместе означают, что к тому моменту, когда у вас есть текстовое содержимое, вы не сможете вернуться к содержащемуся элементу, и вы не можете стилизовать настоящий текст. Это, вероятно, значимо, поскольку спуск только позволяет синхронное отслеживание контекста и синтаксический анализ SAX. Восходящие или другие селекторы с участием других осей вносят потребность в более сложных обходах или подобных решениях, что значительно усложнит применение CSS в DOM.

+3

Это правда. Для этого нужен XPath. Если вы можете выполнить селектор в JS/jQuery или в библиотеке синтаксического анализа (в отличие от CSS-only), тогда можно будет использовать функцию 'text()' XPath. –

+0

Мне это оправдания. css - один из худших языков, с которыми я встречался. Используя? + @ #> И пространство (для крика вслух!), Поскольку ключевые слова для основной логики так восходят к 1980-м годам.По крайней мере, они могли бы использовать существующий ужасный контр-интуитивный язык-селектор, такой как регулярное выражение или xpath, они равномерно плохи, но по крайней мере вам не нужно было бы изучать другой. Лучшее, что они могли сделать, это использовать порт js, как для селекторов, свойств и значений. По крайней мере, таким образом, вы могли бы центрировать элемент в своем контейнере, когда речь идет о боковом элементе, например. – oriadam

3

Для тех, кто хочет сделать Selenium CSS text selections, этот скрипт может пригодиться.

Хитрость заключается в том, чтобы выбрать родительский элемент, который вы ищете, а затем искать для ребенка, который имеет текст:

public static IWebElement FindByText(this IWebDriver driver, string text) 
{ 
    var list = driver.FindElement(By.CssSelector("#RiskAddressList")); 
    var element = ((IJavaScriptExecutor)driver).ExecuteScript(string.Format(" var x = $(arguments[0]).find(\":contains('{0}')\"); return x;", text), list); 
    return ((System.Collections.ObjectModel.ReadOnlyCollection<IWebElement>)element)[0]; 
} 

Это будет возвращать первый элемент, если есть больше чем один так как это всегда один элемент, в моем случае.

4

Поскольку CSS не хватает этой функции, вам придется использовать javascript для стилей элементов по контенту. Например, с помощью XPath содержит

var elms = document.evaluate("//td[contains(., 'male')]" ,node, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null) 

Затем используйте результат как так:

for (var i=0 ; i < elms.snapshotLength; i++){ 
    elms.snapshotItem(i).style.background = "pink"; 
} 

https://jsfiddle.net/gaby_de_wilde/o7bka7Ls/9/

+0

Это javascript, как это связано с вопросом? – rubo77

+0

Как вы не можете выбрать по контенту в css, вам нужно будет использовать js для этого. Хотя вы правы, когда указываете, что это не css, использование атрибута данных не выбирается по контенту. Мы можем только догадываться, почему читатель хочет выбрать ячейки по контенту, какой доступ у нее к html, сколько совпадений, насколько большой стол и т. Д. И т. Д. – user40521

9

Вы можете установить содержание в качестве атрибутов данных, а затем использовать attribute selectors

/* Select every cell containing word "male" */ 
 
td[data-content="male"] { 
 
    color: red; 
 
} 
 

 
/* Select every cell starting on "p" case insensitive */ 
 
td[data-content^="p" i] { 
 
    color: blue; 
 
} 
 

 
/* Select every cell containing "4" */ 
 
td[data-content*="4"] { 
 
    color: green; 
 
}
<table> 
 
    <tr> 
 
    <td data-content="Peter">Peter</td> 
 
    <td data-content="male">male</td> 
 
    <td data-content="34">34</td> 
 
    </tr> 
 
    <tr> 
 
    <td data-conten="Susanne">Susanne</td> 
 
    <td data-content="female">female</td> 
 
    <td data-content="14">14</td> 
 
    </tr> 
 
</table>

Вы также можете использовать JQuery легко установить эти данные атрибутов-контент

$(function(){ 
    $("td").each(function(){ 
    var $this = $(this); 
    $this.attr("data-content", $this.text()); 
    }); 
}); 
+1

Это очень удобный трюк для сгенерированной разметки – Whelkaholism

+2

. text() 'и' .textContent' довольно тяжелые, старайтесь избегать их в длинных списках или больших текстах, когда это возможно. '.html()' и '.innerHTML' бывают быстрыми. – oriadam

1

@ ответ Вояджера об использовании data-* атрибута (например, data-gender="female|male" является наиболее эффективным и соответствует стандартам подхода как в 2017 году:

[data-gender='male'] {background-color: #000; color: #ccc;} 

Довольно много больше голов может быть достигнуты, поскольку есть некоторые хотя и ограниченные селекторы ориентированных вокруг текста. ::first-letter - это pseudo-element, который может применять ограниченный стиль к первой букве элемента. Существует также псевдоэлемент ::first-line, кроме того, что, очевидно, выбор первой строки элемента (например, параграф) также подразумевает, что очевидно, что CSS можно использовать для расширения этой существующей возможности для стилизации определенных аспектов текстового элемента.

Пока такая пропаганда не удастся и реализована следующая лучшая вещь, которую я мог бы предложить, когда это применимо, чтобы explode/split слов с использованием космического deliminator, выход каждого отдельного слова внутри span элемента, а затем, если слово/стайлинг цель предсказуем использование в сочетании с :nth selectors:

$p = explode(' ',$words); 
foreach ($p as $key1 => $value1) 
{ 
echo '<span>'.$value1.'</span>; 
} 

Else если не предсказуемы, опять же, использовать ответ Вояджера об использовании data-* атрибута. Пример использования PHP:

$p = explode(' ',$words); 
foreach ($p as $key1 => $value1) 
{ 
echo '<span data-word="'.$value1.'">'.$value1.'</span>; 
} 
1

Я согласен the data attribute (ответ Вояджера), как это должно быть обработано, НО, правила CSS, такие как:

td.male { color: blue; } 
td.female { color: pink; } 

часто может быть гораздо проще установить особенно с клиентскими библиотеками, такими как angularjs, которые могут быть такими же простыми, как:

<td class="{{person.gender}}"> 

Просто убедитесь, что содержание - всего лишь одно слово!Или вы могли бы даже сопоставить с различными именами классов CSS с:

<td ng-class="{'masculine': person.isMale(), 'feminine': person.isFemale()}"> 

Для полноты картины, вот данные атрибутов подход:

<td data-gender="{{person.gender}}"> 
1

Большинство ответов здесь пытаются предложить альтернативу, как писать HTML чтобы включить больше данных, потому что по крайней мере до CSS3 вы не можете выбрать элемент путем частичного внутреннего текста. Но это может быть сделано, вам просто нужно добавить немного ванили JavaScript, обратите внимание, поскольку женщина содержит также мужчина будет выбран:

 cells = document.querySelectorAll('td'); 
 
    \t console.log(cells); 
 
     [].forEach.call(cells, function (el) { 
 
    \t if(el.innerText.indexOf("male") !== -1){ 
 
    \t //el.click(); click or any other option 
 
    \t console.log(el) 
 
    \t } 
 
    });
<table> 
 
     <tr> 
 
     <td>Peter</td> 
 
     <td>male</td> 
 
     <td>34</td> 
 
     </tr> 
 
     <tr> 
 
     <td>Susanne</td> 
 
     <td>female</td> 
 
     <td>14</td> 
 
     </tr> 
 
    </table>

<table> 
    <tr> 
    <td data-content="Peter">Peter</td> 
    <td data-content="male">male</td> 
    <td data-content="34">34</td> 
    </tr> 
    <tr> 
    <td data-conten="Susanne">Susanne</td> 
    <td data-content="female">female</td> 
    <td data-content="14">14</td> 
    </tr> 
</table> 
0

Если вы используете Chimp/Webdriver.io, они support a lot more CSS selectors, чем спецификация CSS.

Это, к примеру, нажмите на первый якорь, который содержит слова «Bad медведь»:

browser.click("a*=Bad Bear"); 
-1

У меня была такая же проблема с некоторыми плохо сформированной HTML. Все данные, содержащиеся в ярлыках <td>, без дополнительной идентифицирующей информации.

Предостережение: это работает только потому, что в последующем тексте <td> всегда содержалось «значение» для предыдущего текста <td>.

Я искал адреса для всех станций CTA в Чикаго. У меня была база данных с номером станции, поэтому мне удалось создать хеш, связывающий номер станции с адресом с приведенным ниже кодом.

td_hash = {} 
filename = Rails.root + "cta_geojson.geojson" 
page = open(filename) 
parsed_json = JSON.parse(page.read) 
q = parsed_json['features'].map {|e| e['properties']['description'] } #description was a string of badly formed HTML 
q.each do |station| 
    doc = Nokogiri::HTML(station) 
    td = doc.css("td") #collect the td's 
    s_address = 0 #address selector. This goes to 1 when the <td> text is "ADDRESS" becase we know the address is in the next <td> 
    s_gtfs = 0 #gtfs selector. This goes to 1 when the <td> text is "GTFS" because we know the cta number is in the next <td> 
    key = '' 
    value = '' 
    td.each do |td| 
    if s_address == 1 
     value = td.text 
     s_address = 0 
    end 
    if s_gtfs == 1 
     key = td.text 
     td_hash.store(key,value) 
     s_gtfs = 0 
    end 
    if td.text == "ADDRESS" 
     s_address = s_address + 1 
    end 
    if td.text == "GTFS" 
     s_gtfs = s_gtfs + 1 
    end 
    end 
end 
Смежные вопросы