webentwicklung-frage-antwort-db.com.de

Gibt es einen CSS-Selektor für Elemente, die bestimmten Text enthalten?

Ich suche einen CSS-Selektor für die folgende Tabelle:

Peter    | male    | 34
Susanne  | female  | 12

Gibt es einen Selektor für alle TDs, die "male" enthalten?

376
jantimon

Wenn ich die Spezifikation richtig lese, nein. 

Sie können für ein Element den Namen eines Attributs im Element und den Wert eines benannten Attributs in einem Element zuordnen. Ich sehe jedoch nichts für übereinstimmenden Inhalt innerhalb eines Elements.

286
Dean J

JQuery verwenden: 

$('td:contains("male")')
136
moettinger

Sieht so aus, als hätten sie darüber nachgedacht für die CSS3-Spezifikation , aber sie hat den Schnitt nicht gemacht.

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

119
Jeff Beaman

Sie müssen den Zeilen data-gender ein Datenattribut mit einem male- oder female-Wert hinzufügen und den Attributselektor verwenden:

HTML:

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

CSS:

td[data-gender="male"] { ... }
92
Esteban Küber

Es gibt tatsächlich eine sehr konzeptionelle Grundlage dafür, warum dies nicht implementiert wurde. Es ist eine Kombination von grundsätzlich drei Aspekten:

  1. Der Textinhalt eines Elements ist effektiv ein untergeordnetes Element dieses Elements
  2. Sie können den Textinhalt nicht direkt ansprechen
  3. CSS erlaubt keinen Aufstieg mit Selektoren

Diese 3 zusammen bedeuten, dass Sie zu dem Zeitpunkt, zu dem Sie über den Textinhalt verfügen, nicht zum übergeordneten Element zurückkehren können und den aktuellen Text nicht formatieren können. Dies ist wahrscheinlich von Bedeutung, da das Absteigen nur eine eindeutige Verfolgung von Kontext und SAX-Stilanalyse ermöglicht. Aufsteigende oder andere Selektoren, die andere Achsen einbeziehen, führen zu der Notwendigkeit komplexerer Traversen oder ähnlicher Lösungen, die die Anwendung von CSS auf das DOM erheblich erschweren würden.

59
Matt Whipple

Sie können den Inhalt als Datenattribut festlegen und dann Attributselektoren verwenden, wie hier gezeigt:

/* 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>

Sie können auch jQuery verwenden, um die Dateninhaltsattribute einfach festzulegen:

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

Da CSS diese Funktion fehlt, müssen Sie Javascript verwenden, um Zellen nach Inhalt zu gestalten. Zum Beispiel mit xpath enthält

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

Dann verwenden Sie das Ergebnis wie folgt:

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

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

4
user40521

Für diejenigen, die eine Selenium-CSS-Textauswahl durchführen möchten, kann dieses Skript von Nutzen sein.

Der Trick besteht darin, das übergeordnete Element des gesuchten Elements auszuwählen und dann nach dem untergeordneten Element zu suchen, das den Text enthält: 

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

Dies gibt das erste Element zurück, wenn es mehr als ein Element gibt, da es in meinem Fall immer ein Element ist.

4

Ich fürchte, das ist nicht möglich, weil der Inhalt kein Attribut ist und auch nicht über eine Pseudoklasse zugänglich ist. Die vollständige Liste der CSS3-Selektoren finden Sie in der CSS3-Spezifikation .

4
Edwin V.

@ voyagers Antwort zur Verwendung von data-* Attribut (z. B. data-gender="female|male" ist der effektivste und standardkonformste Ansatz ab 2017:

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

Ziemlich viele Ziele können erreicht werden, da es einige, wenn auch begrenzte Selektoren gibt, die sich an Text orientieren. Das :: Anfangsbuchstabe ist ein Pseudo-Element , das den Anfangsbuchstaben eines Elements in begrenztem Umfang formatieren kann. Es gibt auch ein :: first-line Pseudo-Element. Neben der offensichtlichen Auswahl der ersten Zeile eines Elements (z. B. eines Absatzes) bedeutet dies auch, dass CSS verwendet werden könnte, um diese vorhandenen Funktionen zu erweitern um bestimmte Aspekte eines textNode zu formatieren.

Solange eine solche Befürwortung nicht erfolgreich ist und , ist das nächstbeste, was ich vorschlagen könnte, wenn es auf explode/split Wörter zutrifft Verwenden Sie ein Leerzeichen, um jedes einzelne Wort in einem span -Element auszugeben, und verwenden Sie es dann in Kombination, wenn das Wort-/Formatierungsziel vorhersehbar ist mit : n-te Selektoren :

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

Andernfalls , falls nicht vorhersehbar , verwenden Sie erneut die Antwort des Reisenden zur Verwendung von data-* Attribut. Ein Beispiel mit PHP:

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

Ich stimme zu das Datenattribut (Antwort des Voyagers) ist, wie es gehandhabt werden sollte, ABER, CSS-Regeln wie: 

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

ist oft viel einfacher einzurichten, vor allem bei clientseitigen libs wie anglejs, die so einfach sein könnten wie:

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

Stellen Sie nur sicher, dass der Inhalt nur ein Wort ist! Oder Sie können sogar verschiedenen CSS-Klassennamen zuordnen:

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

Der Vollständigkeit halber wird hier der Ansatz für Datenattribute verwendet:

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

Sie können auch content mit attr() und Stiltabellenzellen verwenden, die :not:empty

th::after { content: attr(data-value) }
td::after { content: attr(data-value) }
td[data-value]:not(:empty) {
  color: Fuchsia;
}
<table>
  <tr>
    <th data-value="Peter"></th>
    <td data-value="male">&#x0200B;</td>
    <td data-value="34"></td>
  </tr>
  <tr>
    <th data-value="Susanne"></th>
    <td data-value="female"></td>
    <td data-value="12"></td>
  </tr>
  <tr>
    <th data-value="Lucas"></th>
    <td data-value="male">&#x0200B;</td>
    <td data-value="41"></td>
  </tr>
</table>

Ein ZeroWidthSpace wird zum Ändern der Farbe verwendet und kann mit Vanilla JavaScript hinzugefügt werden:

const hombres = document.querySelectorAll('td[data-value="male"]');
hombres.forEach(hombre => hombre.innerHTML = '&#x0200B;');

Obwohl das <td>s end-Tag kann weggelassen werden , kann dies dazu führen, dass es als nicht leer behandelt wird.

1
Josh Habdas

Die Syntax dieser Frage sieht wie die von Robot Framework aus. In diesem Fall gibt es zwar keinen CSS-Selektor, für den Sie Inhalte verwenden können, jedoch ein SeleniumLibrary-Schlüsselwort, das Sie stattdessen verwenden können. Das Warten bis Element enthält .

Beispiel:

Wait Until Element Contains  | ${element} | ${contains}
Wait Until Element Contains  |  td | male
0

Bei den meisten Antworten wird versucht, eine Alternative zum Schreiben des HTML-Codes mit mehr Daten bereitzustellen, da zumindest bis zu CSS3 ein Element nicht durch einen teilweisen inneren Text ausgewählt werden kann. Aber es kann gemacht werden, Sie müssen nur ein wenig Vanilla JavaScript hinzufügen. Beachten Sie, da female auch male enthält, wird es ausgewählt:

      cells = document.querySelectorAll('td');
    	console.log(cells);
      [].forEach.call(cells, function (el) {
    	if(el.innerText.indexOf("male") !== -1){
    	//el.click(); click or any other option
    	console.log(el)
    	}
    });
 <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

Wenn Sie Chimp / Webdriver.io verwenden, unterstützen sie viel mehr CSS-Selektoren als die CSS-Spezifikation. 

Dies wird zum Beispiel auf den ersten Anker klicken, der die Wörter "Böser Bär" enthält:

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