0

How can I select an image name which is defined in CSS?

I can select that CSS image class using JavaScript, but how can I get the image name inside that class? I want to to do it in Puppeteer/Node.js.

I want to click on this class given below if the image inside the class given below matches paper.gif.

CLASS:

.height-20 span a {
   background-image: url("paper.gif");
   background-color: #cccccc;
}

SELECTOR:

let elements = document.querySelectorAll('.height-20 span a'); // Select all Products but how to get image inside this selector?

CLICKER:

 await page.click(".height-20 span a");

What I want to achieve is given below:

if(css image == paper.gif) {
await page.click(".height-20 span a");
}
Grant Miller
  • 27,532
  • 16
  • 147
  • 165
Sayed Mohd Ali
  • 2,156
  • 3
  • 12
  • 28

2 Answers2

1

You can convert the NodeList obtained from document.querySelectorAll() to an array of Nodes, and then you can filter that array by elements that contain a background-image that equals 'paper.gif':

const elements = [...document.querySelectorAll('.height-20 span a')].filter(e => {
  const background_image = window.getComputedStyle(e).backgroundImage.split('/').pop().replace(/[")]/g, '');
  return background_image === 'paper.gif';
});

This implementation can be placed inside page.evaluate(), and you can click() the element from within that page DOM scope if an element exists that matches the given criteria:

await page.evaluate(() => {
  const elements = [...document.querySelectorAll('.height-20 span a')].filter(e => {
    const background_image = window.getComputedStyle(e).backgroundImage.split('/').pop().replace(/[")]/g, '');
    return background_image === 'paper.gif';
  });

  if (elements.length) {
    elements[0].click();
  }
});
Grant Miller
  • 27,532
  • 16
  • 147
  • 165
  • 1
    Thanks, I will try and will get back to you. I will accept the answer if it worked for me. – Sayed Mohd Ali Nov 09 '18 at 05:51
  • I tried your code but I am getting an error (node:6571) UnhandledPromiseRejectionWarning: ReferenceError: document is not defined. So I checked it out https://stackoverflow.com/questions/32126003/node-js-document-is-not-defined – Sayed Mohd Ali Nov 09 '18 at 06:41
  • @SayedMohdAli It sounds like you might be trying to initialize `elements` without placing it in `page.evaluate()`. The page DOM environment contains the `document` object, but the Node.js environment does not. – Grant Miller Nov 09 '18 at 16:46
  • ok, bro, I will check it out in my code again and will rate you positively if worked. thanks for your time – Sayed Mohd Ali Nov 11 '18 at 12:36
  • I am getting any error now, NodeJS is also working but the click is not working at all. Is there anything to do with the link of the background image? return background_image === 'https://www.example.com/img/icon/a-syed-follow.png'; – Sayed Mohd Ali Nov 12 '18 at 06:33
0

@Grant Miller is correct, +1. I just wanted to provide a simple getStyleFromElement in TypeScript:

export async function getStyleFromElement(page: Page, elementHandle: ElementHandle, cssProperty: string): Promise<string> {
  // page.evaluate evaluates the given function from inside the browser context
  // so elementHandle and cssProperty are not available in the scope of the function.
  // That is why we pass it. Puppeteer automatically converts the elementHandle
  // into the correct DOM element, though

  return page.evaluate((element, property) =>
    window.getComputedStyle(element).getPropertyValue(property), elementHandle, cssProperty);
}

You can now get the background-image by calling:

getStyleFromElement(page, element, "background-image");

And bonus, if you want to extract the URL from inside the url(...) construct:

export function getUrlFromBackgroundImage(backgroundImage: string): string | null {
  if (!backgroundImage) return null;
  const match = backgroundImage.match(/url\("(.*)"\)/);
  if (match) {
    return match[1];
  }
  return null;
}
Andre Pena
  • 56,650
  • 48
  • 196
  • 243