ฉันกำลังมองหาตัวเลือก CSS สำหรับตารางต่อไปนี้:
Peter | male | 34
Susanne | female | 12
มีตัวเลือกใดที่จะตรงกับ TD ทั้งหมดที่มี "male" หรือไม่?
$x
ตอบคำถาม สำหรับคำถามเดิม$x("//td[text()='male']")
ทำเคล็ดลับ
ฉันกำลังมองหาตัวเลือก CSS สำหรับตารางต่อไปนี้:
Peter | male | 34
Susanne | female | 12
มีตัวเลือกใดที่จะตรงกับ TD ทั้งหมดที่มี "male" หรือไม่?
$x
ตอบคำถาม สำหรับคำถามเดิม$x("//td[text()='male']")
ทำเคล็ดลับ
คำตอบ:
ถ้าฉันอ่านข้อมูลจำเพาะอย่างถูกต้องไม่
คุณสามารถจับคู่กับองค์ประกอบชื่อของแอตทริบิวต์ในองค์ประกอบและค่าของแอตทริบิวต์ที่มีชื่อในองค์ประกอบ อย่างไรก็ตามฉันไม่เห็นอะไรเลยสำหรับการจับคู่เนื้อหาภายในองค์ประกอบ
:empty
มีกรณีหนึ่งขอบคือ:
ใช้ jQuery:
$('td:contains("male")')
ดูเหมือนว่าพวกเขามีความคิดเกี่ยวกับเรื่องนี้สำหรับข้อมูลจำเพาะ CSS3 นี้แต่มันไม่ได้ทำให้ตัด
:contains()
CSS3 selector 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"])
กำจัดโฆษณาและเป็นตู้คอนเทนเนอร์
คุณสามารถตั้งค่าเนื้อหาเป็น data data จากนั้นใช้selector attributeดังที่แสดงไว้ที่นี่:
/* 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 เพื่อตั้งค่าคุณสมบัติ data-content ได้อย่างง่ายดาย:
$(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 ขาดคุณสมบัตินี้คุณจะต้องใช้จาวาสคริปต์เพื่อจัดรูปแบบเซลล์ตามเนื้อหา ตัวอย่างเช่นกับ XPath's 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 สคริปต์นี้อาจมีประโยชน์สำหรับคุณ
เคล็ดลับคือการเลือกพาเรนต์ขององค์ประกอบที่คุณกำลังมองหาแล้วค้นหาเด็กที่มีข้อความ:
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')
ถ้าคุณใช้ซีลีเนียม: imho ใช้ได้เฉพาะเมื่อคุณไม่สามารถอัปเดตแหล่งที่มาเพื่อเพิ่มคลาสได้ เช่นถ้าคุณทดสอบรหัสดั้งเดิมหรือ บริษัท ของคุณจะไม่ยอมให้คุณพูดกับ devs (eurgh!) เพราะการทดสอบของคุณจะมีความเปราะและจะแตกหากใครบางคนเปลี่ยนข้อความในภายหลังmasculine
หรือเปลี่ยนภาษา เอกสาร SauceLabs แสดงการใช้contains
ที่นี่ ( saucelabs.com/resources/articles/selenium-tips-css-selectors ) + cc @matas vaitkevicius ฉันพลาดอะไรไปแล้วหรือ
ฉันเห็นด้วยกับ data data (คำตอบของผู้เดินทางรอบโลก) คือวิธีการจัดการ แต่กฎ CSS เช่น:
td.male { color: blue; }
td.female { color: pink; }
มักจะง่ายต่อการตั้งค่าโดยเฉพาะอย่างยิ่งกับ libs ฝั่งไคลเอ็นต์เช่น angularjs ซึ่งอาจง่ายเหมือน:
<td class="{{person.gender}}">
ตรวจสอบให้แน่ใจว่าเนื้อหามีเพียงคำเดียว! หรือคุณสามารถแมปกับชื่อคลาส CSS ที่แตกต่างกันด้วย:
<td ng-class="{'masculine': person.isMale(), 'feminine': person.isFemale()}">
เพื่อความสมบูรณ์นี่คือแนวทางของ data data:
<td data-gender="{{person.gender}}">
@ คำตอบของ voyager เกี่ยวกับการใช้data-*
คุณลักษณะ (เช่นdata-gender="female|male"
เป็นวิธีที่มีประสิทธิภาพและได้มาตรฐานที่สุด ณ ปี 2560:
[data-gender='male'] {background-color: #000; color: #ccc;}
คุณสามารถบรรลุเป้าหมายได้เกือบทั้งหมดโดยมีตัวเลือก จำกัด จำนวนหนึ่งแม้ว่าจะเน้นไปที่ข้อความ :: แรกตัวอักษรเป็นองค์ประกอบหลอกว่าสามารถนำไปใช้จัดแต่งทรงผมที่จะ จำกัด ตัวอักษรตัวแรกขององค์ประกอบ นอกจากนี้ยังมี::องค์ประกอบแรกหลอกองค์ประกอบนอกเหนือจากการเลือกบรรทัดแรกขององค์ประกอบ (เช่นย่อหน้า) เห็นได้ชัดว่ายังเห็นได้ชัดว่า CSS สามารถใช้เพื่อขยายขีดความสามารถที่มีอยู่นี้เพื่อกำหนดลักษณะเฉพาะของ textNode .
จนกว่าการสนับสนุนดังกล่าวจะประสบความสำเร็จและดำเนินการในสิ่งที่ดีที่สุดถัดไปที่ฉันสามารถแนะนำได้เมื่อมีการใช้งานคือการใช้คำexplode
/ split
ตัวเว้นวรรคส่งคำแต่ละคำภายในspan
องค์ประกอบและถ้าคำ / เป้าหมายการออกแบบจัดแต่งทรงผมสามารถใช้ร่วมกันได้ :
$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>;
}
หากคุณใช้Chimp / Webdriver.ioพวกเขาสนับสนุนตัวเลือก CSSมากกว่า CSS spec
ตัวอย่างเช่นนี้จะคลิกที่จุดยึดแรกที่มีคำว่า "Bad bear":
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>
ฉันพบว่าตัวเลือกคุณลักษณะเป็นทางออกที่ดีที่สุดของคุณหากคุณไม่ต้องการใช้ javascript หรือ jquery
เช่นเพื่อจัดเรียงเซลล์ตารางทั้งหมดด้วยคำว่าพร้อมใน HTML ให้ทำดังนี้
<td status*="ready">Ready</td>
จากนั้นใน css:
td[status*="ready"] {
color: red;
}
คุณสามารถใช้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
ใช้เพื่อเปลี่ยนสีและอาจถูกเพิ่มโดยใช้ vanilla JavaScript:
const hombres = document.querySelectorAll('td[data-value="male"]');
hombres.forEach(hombre => hombre.innerHTML = '​');
แม้ว่า<td>
แท็กปิดท้ายนั้นอาจถูกตัดออกไปซึ่งอาจทำให้แท็กนั้นไม่ได้ว่างเปล่า
หากคุณไม่ได้สร้าง DOM ด้วยตัวเอง (เช่นใน userscript) คุณสามารถทำสิ่งต่อไปนี้ด้วย pure 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