How to Check That an Element Is Visible with Puppeteer and Pure JavaScript

How can I check that an element is visible with Puppeteer and pure JavaScript?

I found that Puppeteer has an API method for this purpose: Page.waitForSelector, via its visible option. I wasn't aware of the latter option, but it lets you wait until an element is visible.

await page.waitForSelector('#element', {
visible: true,
})

Conversely you can wait for an element to be hidden, via the hidden option.

I think this is the idiomatic answer, with regards to the Puppeteer API. Thanks to Colin Cline though as I think his answer is probably useful as a general JavaScript solution.

Check if element is visible in DOM

According to this MDN documentation, an element's offsetParent property will return null whenever it, or any of its parents, is hidden via the display style property. Just make sure that the element isn't fixed. A script to check this, if you have no position: fixed; elements on your page, might look like:

// Where el is the DOM element you'd like to test for visibility
function isHidden(el) {
return (el.offsetParent === null)
}

On the other hand, if you do have position fixed elements that might get caught in this search, you will sadly (and slowly) have to use window.getComputedStyle(). The function in that case might be:

// Where el is the DOM element you'd like to test for visibility
function isHidden(el) {
var style = window.getComputedStyle(el);
return (style.display === 'none')
}

Option #2 is probably a little more straightforward since it accounts for more edge cases, but I bet its a good deal slower, too, so if you have to repeat this operation many times, best to probably avoid it.

Get all visible plain text and find out which HTML tag or DOM element each piece of text belongs to

On the client side, you can do this in a way that preserves order using TreeWalker. Here’s an example with sample content from Web Scraper Testing Ground:

const IGNORE = ["style", "script"];
const walker = document.createTreeWalker(document.body, NodeFilter.SHOW_TEXT);
const pairs = [];
let node;
while ((node = walker.nextNode()) !== null) { const parent = node.parentNode.tagName;
if (IGNORE.includes(parent)) { continue; }
const value = node.nodeValue.trim();
if (value.length === 0) { continue; }
pairs.push([parent.toLowerCase(), value]);}
console.log(pairs);
<div id="topbar"></div>  <a href="/" style="text-decoration: none">      <div id="title">WEB SCRAPER TESTING GROUND</div>      <div id="logo"></div>  </a>  <div id="content"><h1>BLOCKS: Price List </h1><div id="caseinfo">In this test, the web scraper needs to scrape a price list organized in a block layout. Specifically, it has to: <ol>  <li>Extract all the products (their names, descriptions and prices), while skipping advertisements</li>  <li>Scrape discounted products only</li>  <li>Scrape products with red prices only</li> </ol><p></p><p>There is a <b>ver</b> parameter (which varies from 1 to 5) to show different table versions (with different product numbers, best price and advertisement positions).</p><p>Also there are two tables presented: </p><ul>  <li><b>Case 1</b> (simple one, with products and prices placed into the same block)  </li><li><b>Case 2</b> (complicated one, with products and prices placed into separate blocks)</li> </ul><p></p><p>For testing, you may use the following sample links. The scraper should sufficiently scrape all data from a certain case using the same project:</p><ul> <li><a href="/blocks?ver=1">Price list 1</a></li> <li><a href="/blocks?ver=2">Price list 2</a></li> <li><a href="/blocks?ver=3">Price list 3</a></li> <li><a href="/blocks?ver=4">Price list 4</a></li> <li><a href="/blocks?ver=5">Price list 5</a></li></ul><p></p></div>
<div id="case_blocks">
<h2>Case 1</h2><div id="case1"><div class="prod2"><span style="float: left"><div class="name">Dell Latitude D610-1.73 Laptop Wireless Computer</div>2 GHz Intel Pentium M, 1 GB DDR2 SDRAM, 40 GB, Microsoft Windows XP Professional</span><span style="float: right">$239.95</span></div><div class="prod1"><span style="float: left"><div class="name">Samsung Chromebook (Wi-Fi, 11.6-Inch)</div>1.7 GHz, 2 GB DDR3 SDRAM, 16 GB, Chrome</span><span style="float: right" class="best">$249.00</span><span style="float: right;margin-right:10px" class="best">BEST<br>PRICE!</span></div><div class="ads">ADVERTISEMENT</div><div class="prod2"><span style="float: left"><div class="name">Apple MacBook Pro MD101LL/A 13.3-Inch Laptop (NEWEST VERSION)</div>2.5 GHz Intel Core i5, 4 GB DDR3 SDRAM, 500 GB Serial ATA, Mac OS X v10.7 Lion</span><span style="float: right">$1,099.99</span></div><div class="prod1"><span style="float: left"><div class="name">Acer Aspire AS5750Z-4835 15.6-Inch Laptop (Black)</div>2 GHz Pentium B940, 4 GB SDRAM, 500 GB, Windows 7 Home Premium 64-bit</span><span style="float: right" class="best">$385.72</span><span style="float: right;margin-right:10px" class="best">BEST<br>PRICE!</span></div><div class="ads">ADVERTISEMENT</div><div class="prod2"><span style="float: left"><div class="name">HP Pavilion g7-2010nr 17.3-Inch Laptop (Black)</div>2.3 GHz Core i3-2350M, 6 GB SDRAM, 640 GB, Windows 7 Home Premium 64-bit</span><span style="float: right">$549.99<div class="disc">discount 7%</div></span></div><div class="prod1"><span style="float: left"><div class="name">ASUS A53Z-AS61 15.6-Inch Laptop (Mocha)</div>1.4 GHz A-Series Quad-Core A6-3420M, 4 GB DIMM, 750 GB, Windows 7 Home Premium 64-bit</span><span style="float: right">$399.99</span></div></div>
<h2 style="margin-top: 50px">Case 2</h2><div id="case2"><div class="left"><div class="prod2"><div class="name">Dell Latitude D610-1.73 Laptop Wireless Computer</div>2 GHz Intel Pentium M, 1 GB DDR2 SDRAM, 40 GB, Microsoft Windows XP Professional</div><div class="prod1"><div class="name">Samsung Chromebook (Wi-Fi, 11.6-Inch)</div>1.7 GHz, 2 GB DDR3 SDRAM, 16 GB, Chrome</div><div class="ads">ADVERTISEMENT</div><div class="prod2"><div class="name">Apple MacBook Pro MD101LL/A 13.3-Inch Laptop (NEWEST VERSION)</div>2.5 GHz Intel Core i5, 4 GB DDR3 SDRAM, 500 GB Serial ATA, Mac OS X v10.7 Lion</div><div class="prod1"><div class="name">Acer Aspire AS5750Z-4835 15.6-Inch Laptop (Black)</div>2 GHz Pentium B940, 4 GB SDRAM, 500 GB, Windows 7 Home Premium 64-bit</div></div><div class="right"><div class="price2">$239.95</div><div class="price1 best">$249.00</div><div class="ads"></div><div class="price2">$1,099.99</div><div class="price1 best">$385.72</div></div><div class="ads" style="clear: both">ADVERTISEMENT</div><div class="left"><div class="prod2"><div class="name">HP Pavilion g7-2010nr 17.3-Inch Laptop (Black)</div>2.3 GHz Core i3-2350M, 6 GB SDRAM, 640 GB, Windows 7 Home Premium 64-bit</div><div class="prod1"><div class="name">ASUS A53Z-AS61 15.6-Inch Laptop (Mocha)</div>1.4 GHz A-Series Quad-Core A6-3420M, 4 GB DIMM, 750 GB, Windows 7 Home Premium 64-bit</div></div><div class="right"><div class="price2">$549.99<div class="disc">discount 7%</div></div><div class="price1">$399.99</div></div></div>
</div><br><br><br> </div>

How do I make puppeteer wait for element to load (in a loop)?

after some searching and trying different pieces of code , i came to a solution and it was using the.$eval() method to access html attributes and checking the height of the element( you could also check other things as well like display or visibility )

const isNotHidden = await mainPage.$eval(
"#some_id",
elem => {
return (
window.getComputedStyle(elem).getPropertyValue("height") >= "5px"
);
}
);

link to main answer that helped me achieve this : https://stackoverflow.com/a/47713155/11968594

puppeteer page.type() select second element/class

I was able to solve it using the following css selector

await page.type(".nxcard:last-child input:nth-child(1)" , "user1")

src : https://www.w3schools.com/cssref/css_selectors.asp



Related Topics



Leave a reply



Submit