primer - selectores css




¿Hay un selector de CSS para los elementos que contienen cierto texto? (10)

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

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


En realidad, existe una base muy conceptual por la cual esto no se ha implementado. Es una combinación de básicamente 3 aspectos:

  1. El contenido de texto de un elemento es efectivamente un elemento secundario de ese elemento.
  2. No puedes dirigir el contenido del texto directamente
  3. 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.


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>

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.


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());
  });
});


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")')




css-selectors