ฉันจะค้นหา DIV พร้อมข้อความบางอย่างได้อย่างไร ตัวอย่างเช่น:
<div>
SomeText, text continues.
</div>
พยายามใช้สิ่งนี้:
var text = document.querySelector('div[SomeText*]').innerTEXT;
alert(text);
แต่แน่นอนมันจะไม่ทำงาน ฉันจะทำมันได้อย่างไร?
ฉันจะค้นหา DIV พร้อมข้อความบางอย่างได้อย่างไร ตัวอย่างเช่น:
<div>
SomeText, text continues.
</div>
พยายามใช้สิ่งนี้:
var text = document.querySelector('div[SomeText*]').innerTEXT;
alert(text);
แต่แน่นอนมันจะไม่ทำงาน ฉันจะทำมันได้อย่างไร?
คำตอบ:
คำถาม OP เป็นเรื่องเกี่ยวกับธรรมดาJavaScriptและไม่jQuery แม้ว่าจะมีคำตอบมากมายและฉันชอบคำตอบของ @Pawan Nogariya โปรดตรวจสอบทางเลือกนี้
คุณสามารถใช้XPATHใน JavaScript ข้อมูลเพิ่มเติมเกี่ยวกับบทความ MDN ที่นี่
document.evaluate()
วิธีการประเมินผลการสอบถาม XPATH / การแสดงออก ดังนั้นคุณสามารถส่งนิพจน์ XPATH ที่นั่นสำรวจเข้าไปในเอกสาร HTML และค้นหาองค์ประกอบที่ต้องการ
ใน XPATH คุณสามารถเลือกองค์ประกอบโดยโหนดข้อความดังต่อไปนี้ whch รับสิ่งdiv
ที่มีโหนดข้อความต่อไปนี้
//div[text()="Hello World"]
หากต้องการรับองค์ประกอบที่มีข้อความให้ใช้ดังต่อไปนี้:
//div[contains(., 'Hello')]
contains()
วิธีการในการใช้เวลา XPATH โหนดเป็นพารามิเตอร์แรกและข้อความเพื่อค้นหาเป็นพารามิเตอร์ที่สอง
ตรวจสอบกลุ่มนี้ที่นี่นี่คือตัวอย่างการใช้ XPATH ใน JavaScript
นี่คือข้อมูลโค้ด:
var headings = document.evaluate("//h1[contains(., 'Hello')]", document, null, XPathResult.ANY_TYPE, null );
var thisHeading = headings.iterateNext();
console.log(thisHeading); // Prints the html element in console
console.log(thisHeading.textContent); // prints the text content in console
thisHeading.innerHTML += "<br />Modified contents";
อย่างที่คุณเห็นฉันสามารถจับองค์ประกอบ HTML และปรับเปลี่ยนได้ตามต้องการ
alert(thisHeading.textContent.replace(/.*You have login (.*) times.*/,'$1')) ;
.evaluate()
ใช้โปรดมีคนแก้ไขฉันถ้าฉันผิด) ประการแรกคุณไม่สามารถค้นหาสิ่งที่ตรงกับนิพจน์ทั่วไปได้ ประการที่สอง.textContent
คุณสมบัติจะส่งคืนโหนดข้อความขององค์ประกอบ หากคุณต้องการดึงค่าออกจากข้อความนี้คุณควรจัดการกับมันอย่างชัดเจนโดยอาจเป็นการสร้างฟังก์ชันบางประเภทที่ตรงกับนิพจน์ทั่วไปและส่งคืนค่าที่ตรงกันในกลุ่มสำหรับคำถามนั้นให้สร้างคำถามใหม่ในเธรดที่แยกต่างหาก
คุณสามารถใช้วิธีง่ายๆนี้:
Array.from(document.querySelectorAll('div'))
.find(el => el.textContent === 'SomeText, text continues.');
Array.from
จะแปลง NodeList ไปยังอาร์เรย์ (มีหลายวิธีที่จะทำเช่นนี้ผู้ประกอบการแพร่กระจายหรือชิ้น)
ผลลัพธ์ตอนนี้คืออาร์เรย์อนุญาตให้ใช้Array.find
เมธอดจากนั้นคุณสามารถใส่เพรดิเคตใดก็ได้ คุณยังสามารถตรวจสอบ textContent ด้วยนิพจน์ทั่วไปหรืออะไรก็ได้ที่คุณต้องการ
โปรดทราบว่าArray.from
และArray.find
เป็นคุณสมบัติของ ES2015 Te เข้ากันได้กับเบราว์เซอร์รุ่นเก่าเช่น IE10 โดยไม่ต้องใช้ Transpiler:
Array.prototype.slice.call(document.querySelectorAll('div'))
.filter(function (el) {
return el.textContent === 'SomeText, text continues.'
})[0];
find
filter
เนื่องจากคุณถามในจาวาสคริปต์เพื่อให้คุณสามารถมีสิ่งนี้ได้
function contains(selector, text) {
var elements = document.querySelectorAll(selector);
return Array.prototype.filter.call(elements, function(element){
return RegExp(text).test(element.textContent);
});
}
แล้วเรียกแบบนี้
contains('div', 'sometext'); // find "div" that contain "sometext"
contains('div', /^sometext/); // find "div" that start with "sometext"
contains('div', /sometext$/i); // find "div" that end with "sometext", case-insensitive
[object HTMLDivElement],[object HTMLDivElement]
foundDivs[0].innerText
ง่ายๆ
โซลูชันนี้ทำสิ่งต่อไปนี้:
ใช้ตัวดำเนินการสเปรด ES6 เพื่อแปลง NodeList ของ all div
s เป็นอาร์เรย์
ให้การส่งออกถ้าdiv
มีสตริงการสืบค้นที่ไม่เพียง แต่ถ้ามันตรงเท่ากับสตริงการสืบค้น (ซึ่งเกิดขึ้นสำหรับบางส่วนของคำตอบอื่น ๆ ) เช่นควรให้ผลลัพธ์ไม่เพียง แต่สำหรับ 'SomeText' แต่ยังรวมถึง 'SomeText, text ต่อไป'
แสดงdiv
เนื้อหาทั้งหมดไม่ใช่เฉพาะสตริงแบบสอบถาม เช่นสำหรับ "SomeText ข้อความจะดำเนินต่อไป" ควรส่งออกทั้งสตริงไม่ใช่แค่ "SomeText"
ช่วยให้หลาย ๆที่จะมีสตริงไม่เพียงหนึ่งเดียวdiv
div
[...document.querySelectorAll('div')] // get all the divs in an array
.map(div => div.innerHTML) // get their contents
.filter(txt => txt.includes('SomeText')) // keep only those containing the query
.forEach(txt => console.log(txt)); // output the entire contents of those
<div>SomeText, text continues.</div>
<div>Not in this div.</div>
<div>Here is more SomeText.</div>
innerHTML
สำหรับคนที่เก่งที่สุด<div>
ของคุณ คุณควรกรองdiv
s ที่มีลูกก่อน ยังสงสัยว่าdocument.getElementsByTagName('div')
อาจเร็วกว่า แต่ฉันจะเปรียบเทียบเพื่อให้แน่ใจ
คุณควรดูว่าคุณมีองค์ประกอบหลักของ div ที่คุณกำลังค้นหาหรือไม่ หากเป็นเช่นนั้นให้รับองค์ประกอบหลักและดำเนินการelement.querySelectorAll("div")
. เมื่อคุณได้รับแล้วให้nodeList
ใช้ตัวกรองกับinnerText
คุณสมบัตินั้น สมมติว่าองค์ประกอบหลักของ div ที่ว่าเรามีการสอบถามมีของid
container
โดยปกติคุณสามารถเข้าถึงคอนเทนเนอร์ได้โดยตรงจาก id แต่ลองทำตามวิธีที่เหมาะสม
var conty = document.getElementById("container"),
divs = conty.querySelectorAll("div"),
myDiv = [...divs].filter(e => e.innerText == "SomeText");
นั่นแหล่ะ
หากคุณไม่ต้องการใช้ jquery หรืออะไรทำนองนั้นคุณสามารถลองสิ่งนี้:
function findByText(rootElement, text){
var filter = {
acceptNode: function(node){
// look for nodes that are text_nodes and include the following string.
if(node.nodeType === document.TEXT_NODE && node.nodeValue.includes(text)){
return NodeFilter.FILTER_ACCEPT;
}
return NodeFilter.FILTER_REJECT;
}
}
var nodes = [];
var walker = document.createTreeWalker(rootElement, NodeFilter.SHOW_TEXT, filter, false);
while(walker.nextNode()){
//give me the element containing the node
nodes.push(walker.currentNode.parentNode);
}
return nodes;
}
//call it like
var nodes = findByText(document.body,'SomeText');
//then do what you will with nodes[];
for(var i = 0; i < nodes.length; i++){
//do something with nodes[i]
}
เมื่อคุณมีโหนดในอาร์เรย์ที่มีข้อความแล้วคุณสามารถทำบางสิ่งกับพวกมันได้ เช่นเดียวกับการแจ้งเตือนแต่ละรายการหรือพิมพ์ลงในคอนโซล ข้อแม้อย่างหนึ่งคือสิ่งนี้อาจไม่จำเป็นต้องคว้า div ต่อ se ซึ่งจะจับพาเรนต์ของโหนดข้อความที่มีข้อความที่คุณกำลังมองหา
เนื่องจากไม่มีการจำกัดความยาวของข้อความในแอตทริบิวต์ข้อมูลให้ใช้แอตทริบิวต์ข้อมูล! จากนั้นคุณสามารถใช้ตัวเลือก css ปกติเพื่อเลือกองค์ประกอบของคุณตามที่ OP ต้องการ
for (const element of document.querySelectorAll("*")) {
element.dataset.myInnerText = element.innerText;
}
document.querySelector("*[data-my-inner-text='Different text.']").style.color="blue";
<div>SomeText, text continues.</div>
<div>Different text.</div>
ตามหลักการแล้วคุณจะทำส่วนการตั้งค่าแอตทริบิวต์ข้อมูลในการโหลดเอกสารและ จำกัด ตัวเลือก querySelectorAll ให้แคบลงเล็กน้อยเพื่อประสิทธิภาพ
Google มีสิ่งนี้เป็นผลลัพธ์อันดับต้น ๆ สำหรับผู้ที่ต้องการค้นหาโหนดที่มีข้อความบางอย่าง โดยวิธีการอัปเดตตอนนี้ nodelist สามารถทำซ้ำได้ในเบราว์เซอร์สมัยใหม่โดยไม่ต้องแปลงเป็นอาร์เรย์
โซลูชันสามารถใช้ forEach เช่นนั้นได้
var elList = document.querySelectorAll(".some .selector");
elList.forEach(function(el) {
if (el.innerHTML.indexOf("needle") !== -1) {
// Do what you like with el
// The needle is case sensitive
}
});
สิ่งนี้ได้ผลสำหรับฉันในการค้นหา / แทนที่ข้อความภายใน nodelist เมื่อตัวเลือกปกติไม่สามารถเลือกเพียงโหนดเดียวได้ดังนั้นฉันจึงต้องกรองแต่ละโหนดทีละโหนดเพื่อตรวจสอบเข็ม
ใช้ XPath และ document.evaluate () และตรวจสอบให้แน่ใจว่าใช้ text () ไม่ใช่ สำหรับอาร์กิวเมนต์มี () มิฉะนั้นคุณจะมี HTML ทั้งหมดหรือองค์ประกอบ div ด้านนอกสุดที่ตรงกัน
var headings = document.evaluate("//h1[contains(text(), 'Hello')]", document, null, XPathResult.ANY_TYPE, null );
หรือไม่สนใจช่องว่างที่นำหน้าและต่อท้าย
var headings = document.evaluate("//h1[contains(normalize-space(text()), 'Hello')]", document, null, XPathResult.ANY_TYPE, null );
หรือจับคู่แท็กทุกประเภท (div, h1, p ฯลฯ )
var headings = document.evaluate("//*[contains(text(), 'Hello')]", document, null, XPathResult.ANY_TYPE, null );
จากนั้นทำซ้ำ
let thisHeading;
while(thisHeading = headings.iterateNext()){
// thisHeading contains matched node
}
thisheading.setAttribute('class', "esubject")
นี่คือแนวทาง XPath แต่มีศัพท์แสง XPath ขั้นต่ำ
การเลือกปกติตามค่าแอตทริบิวต์องค์ประกอบ (สำหรับการเปรียบเทียบ):
// for matching <element class="foo bar baz">...</element> by 'bar'
var things = document.querySelectorAll('[class*="bar"]');
for (var i = 0; i < things.length; i++) {
things[i].style.outline = '1px solid red';
}
การเลือก XPath ตามข้อความภายในองค์ประกอบ
// for matching <element>foo bar baz</element> by 'bar'
var things = document.evaluate('//*[contains(text(),"bar")]',document,null,XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,null);
for (var i = 0; i < things.snapshotLength; i++) {
things.snapshotItem(i).style.outline = '1px solid red';
}
และนี่คือกรณีที่ไม่ตอบสนองเนื่องจากข้อความมีความผันผวนมากขึ้น:
// for matching <element>foo bar baz</element> by 'bar' case-insensitively
var things = document.evaluate('//*[contains(translate(text(),"ABCDEFGHIJKLMNOPQRSTUVWXYZ","abcdefghijklmnopqrstuvwxyz"),"bar")]',document,null,XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,null);
for (var i = 0; i < things.snapshotLength; i++) {
things.snapshotItem(i).style.outline = '1px solid red';
}
ฉันมีปัญหาที่คล้ายกัน
ฟังก์ชันที่ส่งคืนองค์ประกอบทั้งหมดซึ่งรวมถึงข้อความจาก arg
สิ่งนี้ใช้ได้กับฉัน:
function getElementsByText(document, str, tag = '*') {
return [...document.querySelectorAll(tag)]
.filter(
el => (el.text && el.text.includes(str))
|| (el.children.length === 0 && el.outerText && el.outerText.includes(str)))
}
มีวิธีแก้ปัญหาที่ยอดเยี่ยมมากมายที่นี่แล้ว อย่างไรก็ตามเพื่อให้เป็นโซลูชันที่มีความคล่องตัวมากขึ้นและอีกหนึ่งวิธีที่สอดคล้องกับแนวคิดของพฤติกรรมและไวยากรณ์ของ querySelector ฉันเลือกใช้โซลูชันที่ขยายObjectด้วยฟังก์ชันต้นแบบสองสามฟังก์ชัน ฟังก์ชันทั้งสองนี้ใช้นิพจน์ทั่วไปสำหรับข้อความที่ตรงกันอย่างไรก็ตามสามารถระบุสตริงเป็นพารามิเตอร์การค้นหาแบบหลวม ๆ ได้
เพียงใช้ฟังก์ชันต่อไปนี้:
// find all elements with inner text matching a given regular expression
// args:
// selector: string query selector to use for identifying elements on which we
// should check innerText
// regex: A regular expression for matching innerText; if a string is provided,
// a case-insensitive search is performed for any element containing the string.
Object.prototype.queryInnerTextAll = function(selector, regex) {
if (typeof(regex) === 'string') regex = new RegExp(regex, 'i');
const elements = [...this.querySelectorAll(selector)];
const rtn = elements.filter((e)=>{
return e.innerText.match(regex);
});
return rtn.length === 0 ? null : rtn
}
// find the first element with inner text matching a given regular expression
// args:
// selector: string query selector to use for identifying elements on which we
// should check innerText
// regex: A regular expression for matching innerText; if a string is provided,
// a case-insensitive search is performed for any element containing the string.
Object.prototype.queryInnerText = function(selector, text){
return this.queryInnerTextAll(selector, text)[0];
}
เมื่อใช้ฟังก์ชันเหล่านี้คุณสามารถโทรออกได้ดังนี้:
document.queryInnerTextAll('div.link', 'go');
document.queryInnerText('div.link', 'go');
document.queryInnerTextAll('a', /^Next$/);
document.queryInnerText('a', /next/i);
e = document.querySelector('#page');
e.queryInnerText('button', /Continue/);