Я шукаю селектор CSS для наступної таблиці:
Peter | male | 34
Susanne | female | 12
Чи є селектор, який відповідає всім ТД, що містять "чоловічий"?
$x
відповідає на питання. на первісне запитання, $x("//td[text()='male']")
чи трюк
Я шукаю селектор CSS для наступної таблиці:
Peter | male | 34
Susanne | female | 12
Чи є селектор, який відповідає всім ТД, що містять "чоловічий"?
$x
відповідає на питання. на первісне запитання, $x("//td[text()='male']")
чи трюк
Відповіді:
Якщо я правильно прочитав специфікацію , ні.
Ви можете зіставити елемент, ім'я атрибута в елементі та значення назви атрибута в елементі. Я не бачу нічого для відповідності вмісту в межах елемента.
:empty
.
Використання jQuery:
$('td:contains("male")')
Схоже, вони думали про це для специфікації CSS3, але це не вирішило .
:contains()
CSS3-селектор http://www.w3.org/TR/css3-selectors/#content-selectors
Looks like they were thinking about it for the CSS3 spec but it didn't make the cut.
І з поважної причини це порушило б усю передумову розділення стилів, змісту, структури та поведінки.
Ви повинні були б додати атрибут даних в рядках , званих data-gender
з male
або female
значенням і використовувати селектор атрибуту:
HTML:
<td data-gender="male">...</td>
CSS:
td[data-gender="male"] { ... }
male
або female
? Те, що class
заповнено іншими класами, порядок їх не гарантується, можуть виникнути колізії з іншими назвами класів тощо, які class
ще гірші місця для подібних матеріалів. Виділений data-*
атрибут ізолює ваші дані від усіх цих матеріалів та полегшує їх часткове узгодження тощо за допомогою селекторів атрибутів.
Насправді існує дуже концептуальна основа, чому це не було здійснено. Це в основному 3 аспекти:
Ці 3 разом означають, що до моменту отримання текстового вмісту ви вже не можете повернутися до елемента, що містить, і ви не можете стилізувати даний текст. Це, ймовірно, є важливим, оскільки низхідне значення дозволяє лише відстежувати контекст та аналіз стилю SAX. Вихідні чи інші селектори, що включають інші осі, вводять необхідність у складніших обходах або подібних рішеннях, які значно ускладнюють застосування CSS до DOM.
text()
функцію XPath .
:contains(<sub-selector>)
можливість вибрати елементи, які містять інші конкретні елементи. Як div:contains(div[id~="bannerAd"])
би позбутися реклами та її контейнера.
Ви можете встановити вміст як атрибут даних, а потім використовувати селектори атрибутів , як показано тут:
/* 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());
});
});
.text()
і .textContent
вони досить важкі, намагайтеся уникати їх у довгих списках чи великих текстах, коли це можливо. .html()
і .innerHTML
швидко.
$("td:contains(male)")
contenteditable='true'
- мій випадок), недостатньо встановити значення data-content
атрибута до того, як сторінка буде надана. Його потрібно постійно оновлювати. Ось чим я користуюся:<td onkeypress="event.target.setAttribute('data-content', event.target.textContent);">
Оскільки у CSS відсутня ця функція, вам доведеться використовувати JavaScript для стилю комірок за вмістом. Наприклад з XPath contains
:
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";
}
Боюся, що це неможливо, тому що вміст не є атрибутом, і він не доступний через псевдоклас. Повний список селекторів CSS3 можна знайти в специфікації CSS3 .
Для тих, хто хоче зробити підбір тексту CSS Selenium, цей скрипт може бути корисним.
Хитрість полягає в тому, щоб вибрати батьківський елемент елемента, який ви шукаєте, а потім знайти дитину, яка містить текст:
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];
}
Це поверне перший елемент, якщо його буде більше, оскільки це завжди один елемент, в моєму випадку.
TD:contains('male')
якщо ви використовуєте Selenium: imho використовувати його, лише якщо ви не можете оновити джерело для додавання класів. Наприклад, якщо ви тестуєте застарілий код або ваша компанія не дозволяє вам говорити з дияволами (eurgh!), оскільки ваші тести будуть крихкими і зламаються, якщо хтось змінить текст пізніше masculine
або змінить мову. Документи SauceLabs показують використання contains
тут ( saulabs.com/resources/articles/selenium-tips-css-selectors ) + cc @matas vaitkevicius я щось пропустив?
Я погоджуюся, що атрибут даних (відповідь voyager) полягає в тому, як з ним слід обробляти, АЛЕ, такі правила 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}}">
Відповідь @ voyager про використання data-*
атрибуту (наприклад, data-gender="female|male"
це найефективніший та стандартний підхід станом на 2017 рік:
[data-gender='male'] {background-color: #000; color: #ccc;}
Досить більшості цілей можна досягти, оскільки є деякі, хоча і обмежені селектори, орієнтовані навколо тексту. :: першою літерою є псевдо-елементом , який може застосувати обмежений стиль до першої букви елемента. Існує також псевдоелемент :: першого рядка, окрім очевидного вибору першого рядка елемента (наприклад, абзацу), також випливає, що очевидно, що CSS може бути використаний для розширення цієї існуючої можливості для стилювання конкретних аспектів textNode .
Поки таке пропагування не буде успішним і не буде реалізовано наступне найкраще, що я міг би запропонувати, коли це застосовано, до explode
/ split
слів, використовуючи роздільник пробілу, вивести кожне окреме слово всередині span
елемента, а потім, якщо слово / стильова мета передбачувано використовувати у поєднанні з : n-ми селекторами :
$p = explode(' ',$words);
foreach ($p as $key1 => $value1)
{
echo '<span>'.$value1.'</span>;
}
Якщо ще не передбачувано , знову ж таки, використовуйте відповідь voyager про використання data-*
атрибута. Приклад використання PHP:
$p = explode(' ',$words);
foreach ($p as $key1 => $value1)
{
echo '<span data-word="'.$value1.'">'.$value1.'</span>;
}
Якщо ви використовуєте шимпанзе / Webdriver.io , вони підтримують набагато більше CSS селектори , ніж CSS специфікації.
Наприклад, це натисне на перший якір, який містить слова "поганий ведмідь":
browser.click("a*=Bad Bear");
Більшість відповідей тут намагаються запропонувати альтернативу, як написати HTML-код, щоб включити більше даних, оскільки принаймні до CSS3 ви не можете вибрати елемент за допомогою часткового внутрішнього тексту. Але це можна зробити, потрібно лише додати трохи ванільного JavaScript, зауважте, оскільки самка також містить чоловічого, він буде обраний:
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>
Крім того, можна використовувати content
з attr()
і елементів таблиці стилів, які ::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">​</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">​</td>
<td data-value="41"></td>
</tr>
</table>
A ZeroWidthSpace
використовується для зміни кольору і може бути доданий за допомогою ванільного JavaScript:
const hombres = document.querySelectorAll('td[data-value="male"]');
hombres.forEach(hombre => hombre.innerHTML = '​');
Незважаючи на те, <td>
що кінцевий тег s може бути пропущений, це може спричинити його обробку як порожню.
Якщо ви не створюєте DOM самостійно (наприклад, у користувальницькому сценарії), ви можете зробити наступне з чистим JS:
for ( td of document.querySelectorAll('td') ) {
console.debug("text:", td, td.innerText)
td.setAttribute('text', td.innerText)
}
for ( td of document.querySelectorAll('td[text="male"]') )
console.debug("male:", td, td.innerText)
<table>
<tr>
<td>Peter</td>
<td>male</td>
<td>34</td>
</tr>
<tr>
<td>Susanne</td>
<td>female</td>
<td>12</td>
</tr>
</table>
Вихід консолі
text: <td> Peter
text: <td> male
text: <td> 34
text: <td> Susanne
text: <td> female
text: <td> 12
male: <td text="male"> male
Виконайте невеликі віджети фільтру на зразок цього:
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')
}
})
})
Синтаксис цього питання виглядає як синтаксис Robot Framework. У цьому випадку, хоча не існує селектора css, який ви можете використовувати для містить, є ключове слово SeleniumLibrary, яке ви можете використовувати замість цього. Зачекайте , поки елемент містить .
Приклад:
Wait Until Element Contains | ${element} | ${contains}
Wait Until Element Contains | td | male