primer - ¿Hay un selector de CSS para los elementos que contienen cierto texto?
lista de codigos css (14)
Estoy buscando un selector de CSS para la siguiente tabla:
Peter | male | 34
Susanne | female | 12
¿Hay algún selector que coincida con todos los TD que contengan "masculino"?
Como CSS carece de esta función, tendrá que usar javascript para dar estilo a las celdas por contenido. Por ejemplo con xpath contiene
var elms = document.evaluate( "//td[contains(., ''male'')]" ,node, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null )
Luego usa el resultado como tal:
for ( var i=0 ; i < elms.snapshotLength; i++ ){
elms.snapshotItem(i).style.background = "pink";
}
En realidad, existe una base muy conceptual por la cual esto no se ha implementado. Es una combinación de básicamente 3 aspectos:
- El contenido de texto de un elemento es efectivamente un elemento secundario de ese elemento.
- No puedes dirigir el contenido del texto directamente
- CSS no permite la ascensión con selectores.
Estos 3 juntos significan que, para cuando tenga el contenido del texto, no podrá volver al elemento que lo contiene y no podrá aplicar estilo al texto actual. Es probable que esto sea significativo, ya que el descenso solo permite un seguimiento singular del contexto y el análisis de estilo SAX. Los selectores ascendentes u otros que involucran otros ejes introducen la necesidad de soluciones transversales o similares más complejas que complicarían enormemente la aplicación de CSS al DOM.
Estoy de acuerdo en que el atributo de datos (la respuesta del viajero) es cómo debe manejarse, PERO, las reglas de CSS como:
td.male { color: blue; }
td.female { color: pink; }
a menudo puede ser mucho más fácil de configurar, especialmente con libs del lado del cliente como angularjs que podrían ser tan simples como:
<td class="{{person.gender}}">
¡Sólo asegúrate de que el contenido sea una sola palabra! O incluso puedes mapear a diferentes nombres de clases de CSS con:
<td ng-class="{''masculine'': person.isMale(), ''feminine'': person.isFemale()}">
Para completar, aquí está el enfoque de atributos de datos:
<td data-gender="{{person.gender}}">
Haciendo pequeños widgets de filtro como este:
var searchField = document.querySelector(''HOWEVER_YOU_MAY_FIND_IT'')
var faqEntries = document.querySelectorAll(''WRAPPING_ELEMENT .entry'')
searchField.addEventListener(''keyup'', function (evt) {
var testValue = evt.target.value.toLocaleLowerCase();
var regExp = RegExp(testValue);
faqEntries.forEach(function (entry) {
var text = entry.textContent.toLocaleLowerCase();
entry.classList.remove(''show'', ''hide'');
if (regExp.test(text)) {
entry.classList.add(''show'')
} else {
entry.classList.add(''hide'')
}
})
})
La mayoría de las respuestas aquí intentan ofrecer una alternativa a cómo escribir el código HTML para incluir más datos porque al menos hasta CSS3 no se puede seleccionar un elemento con un texto interno parcial. Pero se puede hacer, solo necesitas agregar un poco de JavaScript de vainilla, ya que la hembra también contiene un macho, se seleccionará:
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>
La respuesta de @ voyager sobre el uso del atributo data-*
(por ejemplo, data-gender="female|male"
es el enfoque más eficaz y que cumple con los estándares a partir de 2017:
[data-gender=''male''] {background-color: #000; color: #ccc;}
Casi la mayoría de los objetivos se pueden alcanzar ya que hay algunos selectores limitados orientados alrededor del texto. La ::first-letter es un pseudo-element que puede aplicar un estilo limitado a la primera letra de un elemento. También hay un ::first-line pseudo-elemento de primera línea además de seleccionar obviamente la primera línea de un elemento (como un párrafo) también implica que es obvio que CSS podría utilizarse para ampliar esta capacidad existente para diseñar aspectos específicos de un textNode .
Hasta que dicha promoción tenga éxito y se implemente, lo mejor que podría sugerir cuando aplique es explode
/ split
palabras con un separador de espacio, generar cada palabra individual dentro de un elemento de split
y luego, si el objetivo de estilo / palabra es predecible, en combinación con : nth selectores :
$p = explode('' '',$words);
foreach ($p as $key1 => $value1)
{
echo ''<span>''.$value1.''</span>;
}
De lo contrario, si no es predecible , de nuevo, use la respuesta de voyager sobre el uso del atributo data-*
. Un ejemplo usando PHP:
$p = explode('' '',$words);
foreach ($p as $key1 => $value1)
{
echo ''<span data-word="''.$value1.''">''.$value1.''</span>;
}
Me temo que esto no es posible, porque el contenido no es un atributo ni es accesible a través de una pseudo clase. La lista completa de selectores de CSS3 se puede encontrar en la especificación de CSS3 .
Para aquellos que buscan hacer selecciones de texto de Selenium CSS, este script puede ser de alguna utilidad.
El truco consiste en seleccionar el elemento primario del elemento que está buscando y, a continuación, buscar el elemento secundario que tiene el texto:
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];
}
Esto devolverá el primer elemento si hay más de uno, ya que siempre es un elemento, en mi caso.
Parece que estaban pensando en eso para la especificación de CSS3, pero no llegó al corte .
:contains()
selector CSS3 http://www.w3.org/TR/css3-selectors/#content-selectors
Podría establecer el contenido como atributo de datos y luego usar los selectores de atributos
/* 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>
También puede usar jQuery para configurar fácilmente estos atributos de contenido de datos
$(function(){
$("td").each(function(){
var $this = $(this);
$this.attr("data-content", $this.text());
});
});
Si está utilizando Chimp / Webdriver.io , admiten muchos más selectores de CSS que la especificación de CSS.
Esto, por ejemplo, hará clic en el primer anclaje que contiene las palabras "oso malo":
browser.click("a*=Bad Bear");
Si leo la especificación correctamente, no.
Puede hacer coincidir en un elemento, el nombre de un atributo en el elemento y el valor de un atributo con nombre en un elemento. Sin embargo, no veo nada para hacer coincidir el contenido dentro de un elemento.
Tendría que agregar un atributo de datos a las filas llamadas data-gender
con un valor male
o female
y usar el selector de atributos:
HTML:
<td data-gender="male">...</td>
CSS:
td[data-gender="male"] { ... }
Usando jQuery:
$(''td:contains("male")'')