2009-10-05 9 views
301

szukam selektora CSS w poniższej tabeli:Czy istnieje selektor CSS dla elementów zawierających określony tekst?

Peter | male | 34 
Susanne | female | 12 

Czy istnieje selektor dopasować wszystkie TDS zawierające „męski”?

+1

Problem polega na tym, że byłoby to bardzo trudne do zrealizowania w wydajny sposób. – Ms2ger

+2

Używam teraz jQuery. Działa idealnie. – jantimon

+5

Selektor XPath może to zrobić za pomocą metody .text() (jeśli nie chcesz używać executora JavaScript). – djangofan

Odpowiedz

233

Jeśli poprawnie odczytam the specification, nie.

Można dopasować element, nazwę atrybutu w elemencie i wartość nazwanego atrybutu w elemencie. Jednak nie widzę niczego, co pasuje do treści w obrębie elementu.

+153

Jest jeden przypadek krawędzi: ': empty'. –

+2

Powyższy komentarz musi być wybraną odpowiedzią! –

+9

Czy ta odpowiedź jest nadal aktualna dzisiaj (2016)? –

3

Obawiam się, że nie jest to możliwe, ponieważ treść nie jest atrybutem ani nie jest dostępna za pośrednictwem pseudoklasy. Pełną listę selektorów CSS3 można znaleźć w the CSS3 specification.

86

Trzeba dodać atrybut danych do wierszy zwanych data-gender z male lub female wartości i użyć selektora atrybutu:

HTML:

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

CSS:

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

Sprytne rozwiązanie. Dzięki –

+1

Atrybuty danych nie są używane jako haki JS lub selektory CSS - do tego służą klasy. Ze specyfikacji: 'Niestandardowe atrybuty danych służą do przechowywania niestandardowych danych prywatnych do strony lub aplikacji, dla których nie ma już bardziej odpowiednich atrybutów lub elementów." Link do specyfikacji: [link] (http: // www .w3.org/html/wg/drafty/html/master/dom.html # osadzanie-niestandardowe-niewidoczne-dane-z-danymi-* - atrybuty) –

+10

@Ivan Durst, szczerze się nie zgadzam, jak JS haki lub selektory CSS spełniają definicję danych prywatnych do strony lub aplikacji, a tam NIE jest bardziej odpowiedni semantyczny html dla płci. Im więcej odpowiedzialności spoczywa na atrybucie klasy, tym dalej otrzymujemy semantyczny html, więc zaczynam korzystać ze zwiększonych metadanych dostępnych w html5. – DannyMeister

98

Wygląda na to, że myśleli o tym dla specyfikacji CSS3 , ale nie spowodowało to cięcia.

:contains() selektor CSS3 http://www.w3.org/TR/css3-selectors/#content-selectors

+19

Ostatnią dostępną definicję': zawiera() 'można znaleźć [tutaj] (http://www.w3.org/TR/2001/CR-css3-selectors-20011113/#content-selectors). – BoltClock

+2

'Wygląda na to, że myśleli o tym dla specyfikacji CSS3, ale nie spowodowało to cięcia." I nie bez powodu złamałoby to całą zasadę oddzielania stylizacji, treści, struktury i zachowania. – Synetech

+26

@Synetech W rzeczywistości może pomóc w oddzieleniu stylizacji od treści, ponieważ oznacza, że ​​treść nie musi wiedzieć o jej kliencie, będzie uważana za ważną dla oparcia stylizacji. W tej chwili nasza zawartość html jest zazwyczaj ściśle powiązana z css, włączając w to klasy, o których wiemy, że styler się tym zajmuje. Już teraz przesuwają się w kierunku udostępniania CSS w treści, o czym świadczą selektory wartości atrybutów w CSS3. – DannyMeister

128

jQuery:

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

Koniec wymagający odwrotności tego, co jest: jQuery (element) .not (": contains ('string')") – Jazzy

+130

Z wyjątkiem tego, że nie jest to CSS, czyli JavaScript. – Synetech

+5

Zgadzam się - dlatego moja odpowiedź mówi, że używam jQuery, a nie CSS. Ale ta część mojej odpowiedzi została zredagowana. =) – moettinger

54

Jest rzeczywiście bardzo koncepcyjny podstawą dlaczego to nie zostało zrealizowane. Jest to kombinacja basically 3 aspektach:

  1. Zawartość tekst elementu jest skutecznie dzieckiem tego elementu
  2. Nie można kierować na zawartość tekstową bezpośrednio
  3. CSS nie pozwala na wniebowstąpieniu z selektorów

Te 3 razem oznaczają, że do czasu, gdy masz zawartość tekstową, nie możesz wznieść się z powrotem do elementu zawierającego i nie możesz zmienić stylu bieżącego tekstu. Jest to prawdopodobnie znaczące, ponieważ opuszczanie pozwala tylko na pojedyncze śledzenie kontekstu i parsowanie stylu SAX. Rosnąco lub inne selektory obejmujące inne osie wprowadzają potrzebę bardziej złożonych rozwiązań lub podobnych rozwiązań, które znacznie komplikują zastosowanie CSS do DOM.

+3

To prawda. Właśnie do tego służy XPath. Jeśli możesz wykonać selektor w JS/jQuery lub bibliotece parsowania (w przeciwieństwie do CSS-only), wówczas możliwe byłoby użycie funkcji 'text()' XPath. –

+0

Dla mnie to są wymówki. css to jeden z najgorszych języków, jakie spotkałem. Używając? + @ #> I spacji (do głośnego krzyczenia!), Ponieważ słowa kluczowe dla podstawowej logiki sięgają lat osiemdziesiątych.W najmniejszym stopniu mogliby wykorzystać istniejący przerażający, sprzeczny z intuicją język wyboru, taki jak regex lub xpath, są one jednakowo złe, ale przynajmniej nie musielibyście uczyć się innego. Najlepsze, co mogli zrobić, to użycie portu js, zarówno dla selektorów, właściwości i wartości. Przynajmniej w ten sposób można wyśrodkować element w swoim pojemniku, na przykład w odniesieniu do elementu bocznego. – oriadam

3

Dla tych, którzy szukają selekcji tekstu selekcji CSS, ten skrypt może być przydatny.

Sztuką jest wybrać nadrzędny element, który szukasz, a następnie szukał Dziecięcia, które ma tekst:

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]; 
} 

ten powróci pierwszy element, jeśli istnieje więcej niż jeden ponieważ w moim przypadku jest to zawsze jeden element.

4

Ponieważ w CSS brakuje tej funkcji, będziesz musiał używać javascript do stylu komórek według treści. Na przykład z XPath zawiera

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

Następnie użyj wynik tak:

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

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

+0

to jest javascript, Jak to jest związane z pytaniem? – rubo77

+0

Ponieważ nie możesz wybrać treści w css, musisz użyć js, aby to zrobić. Chociaż masz rację, gdy zwracasz uwagę, że nie jest to css, użycie atrybutu danych nie wybiera według treści. Możemy się tylko domyślać, dlaczego czytelnik chce wybierać komórki według treści, jaki ma dostęp do html, ile dopasowań, jak duży jest stół itp. Itd. – user40521

9

Można ustawić zawartość jako atrybut danych, a następnie użyć 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>

Można również użyć jQuery łatwo ustawić te dane-content atrybuty

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

To naprawdę przydatna sztuczka dla wygenerowanego znacznika – Whelkaholism

+2

zauważ, że '. text() 'i' .textContent' są dość ciężkie, staraj się unikać ich na długich listach lub dużych tekstach, gdy tylko jest to możliwe. '.html()' i '.innerHTML' są szybkie. – oriadam

1

@ odpowiedź Voyagera o użyciu atrybutu data-* (np data-gender="female|male" jest najbardziej skuteczny i zgodny z normami podejście jak z 2017 roku:

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

Prawie większość goli może zostać osiągnięte, ponieważ istnieją pewne aczkolwiek ograniczonych selektorów zorientowanych wokół tekstu. Model ::first-letter to pseudo-element, który może stosować ograniczoną stylizację do pierwszej litery elementu. Istnieje również pseudoelement ::first-line oprócz oczywistego wybrania pierwszego wiersza elementu (takiego jak akapit), co oznacza również, że CSS może zostać użyty do rozszerzenia tej istniejącej możliwości, aby stylować określone aspekty węzła textNode.

Do takich rzecznictwo powiedzie i jest realizowana następnego najlepszą rzeczą mógłbym zasugerować, kiedy stosowane jest explode/split słowy wykorzystaniem deliminator przestrzeń, wyjście każdy indywidualny wyraz wewnątrz elementu span i wtedy, gdy słowo/stylizacji cel jest przewidywalny stosowanie w połączeniu z :nth selectors:

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

Else jeśli nie przewidywalny aby ponownie użyć Voyager za odpowiedź na temat korzystania atrybut data-*. Przykładem użyciem PHP:

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

zgadzam the data attribute (odpowiedź Voyagera) jest to, jak powinien być traktowany, ale CSS, takie jak:

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

często może być znacznie łatwiej ustawić w górę, szczególnie w przypadku bibliotek klienckich takich jak angularjs, które mogą być tak proste, jak:

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

Tylko upewnij się, że treść jest tylko jednym słowem!Lub można nawet mapować do różnych nazw klas CSS z:

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

pod względem kompletności, tutaj podejście przypisywać dane:

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

Większość odpowiedzi tutaj staramy się zaoferować alternatywę dla jak napisać kod HTML kod, aby dodać więcej danych, ponieważ przynajmniej do CSS3 nie można wybrać elementu za pomocą częściowego tekstu wewnętrznego. Ale można to zrobić, wystarczy dodać trochę wanilii JavaScript, zawiadomienie zawiera także ponieważ samica samiec zostanie wybrany:

 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> 
-1

miałem ten sam problem z jakimś źle utworzonego html. Wszystkie dane przechowywane na etykietach <td> bez dodatkowych informacji identyfikacyjnych.

Uwaga: działa to tylko dlatego, że następny tekst <td> zawsze zawierał "wartość" poprzedniego tekstu <td>.

Szukałem adresów dla wszystkich stacji CTA w Chicago. Miałem bazę danych z numerem stacji, więc udało mi się utworzyć hasz łączący numer stacji z adresem z poniższym kodem.

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 
Powiązane problemy