1

I'm trying to programatically select a photo from within a Google Photos Album in the browser, via the console.

I've tried the following:

const photo = document.getElementsByClassName('p137Zd')[0].parentElement

photo.querySelectorAll('div[role="checkbox"]').click()

But I'm getting an error. This quick code was meant to trigger a click() event and select the first photo in an album, but I'm getting an error saying:

Uncaught TypeError: photo.parentElement.querySelectorAll(...)[0].click is not a function

Can anyone help me achieve this?

gespinha
  • 7,968
  • 16
  • 57
  • 91

3 Answers3

1

You get a collection from querySelectorAll so this could be a dupe

This is is simpler:

const photo = document.querySelector('.p137Zd').parentElement

In any case try

photo.querySelectorAll('div[role="checkbox"]').forEach(div => div.click());
mplungjan
  • 169,008
  • 28
  • 173
  • 236
0

As the other codes in this thread don't quite work from my experience, I've reused https://stackoverflow.com/a/73154187/22316590, to make it work for me.

document.querySelectorAll('div[role="checkbox"]:not([aria-label*="Select all"]):not([aria-checked="true"])').forEach(div => div.click());

I've added this :not([aria-label*="Select all"]), as I suspect that the Select All is also being clicked, which unselects the images. I've also added :not([aria-checked="true"]), so it doesn't uncheck images.

However, I've noticed that the images/checkboxes have to be rendered on the screen in order for it to work. So there's a lot of scrolling & repeating the command in console.

HBIDamian
  • 1
  • 1
0

The problem is that querySelectorAll returns an array-like-object and it does not have a click() function. The items that are members of this array-like-object are elements and they all have individually a click function, but you cannot invoke it from the array-like-object (a NodeList, to be precise) that contains them.

In the accepted answer of @mplungjan, we see this approach

photo.querySelectorAll('div[role="checkbox"]').forEach(div => div.click());

which is correct.

But, you can also create a click function for a NodeList and then you would be able to run your initial code :)

NodeList.prototype.click = function() {
    for (let item of this) item.click();
};

document.querySelectorAll(".hd").forEach(item => item.parentNode.querySelectorAll("[type=button]").click());
<div>
    <input type="button" value="1" onclick="console.log(1)">
    <input type="button" value="2" onclick="console.log(2)">
    <input type="button" value="3" onclick="console.log(3)">
    <input type="hidden" class="hd">
</div>
<div>
    <input type="button" value="4" onclick="console.log(4)">
    <input type="button" value="5" onclick="console.log(5)">
    <input type="button" value="6" onclick="console.log(6)">
</div>
<div>
    <input type="button" value="7" onclick="console.log(7)">
    <input type="button" value="8" onclick="console.log(8)">
    <input type="button" value="9" onclick="console.log(9)">
    <input type="hidden" class="hd">
</div>

As we can see, once we define a click function for a NodeList that clicks all the elements inside, we can reuse it as many times as we would like.

So, while mplungjan's answer is correct and deserves to be accepted, I have decided to write a new answer about how we can add the feature that you missed here rather than working around it.

Lajos Arpad
  • 64,414
  • 37
  • 100
  • 175