-2

https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons

On the page I linked above, there's a sidebar on the left.

There are drop down lists which requires the user to click on each of them to be able to see the sublists.

I was trying to write a code so that it would click on all toggleable lists to unhide the sublists.

Using click() on the parent element does nothing, I tried all children and subchildren of the parent element and found that this works:

x=document.querySelectorAll(".toggle").children[0].children[1];

So I tried writing a code which does click() on all childrens, I wrote this and it worked:

x=document.querySelectorAll(".toggle");
for(i=0;i<x.length;i++){
    x[i].click();
    y=x[i].children;
    for (j=0;j<y.length;j++){
        y[j].click();
        z=y[j].children;
        for(k=0;k<z.length;k++){
            z[k].click();
        }
    }
}

Since I'm a new JS learner, I tried using the for/in statement but it didn't work:

x=document.querySelectorAll(".toggle");
for(i in x){
    x[i].click();
    y=x[i].children;
    for (j in y){
        y[j].click();
        z=y[j].children;
        for(k in z){
            z[k].click();
        }
    }
}
Uncaught TypeError: z[k].click is not a function
at <anonymous>:9:9

I also tried forEach method and this also doesn't work:

x=document.querySelectorAll(".toggle");
var y; var z;
x.forEach(i);
function i(item, index){
    item.click();
    y=item.children;
    y.forEach(j);
}
function j(item,index){
    item.click();
    z=item.children;
    z.forEach(k);
}
function k(item,index){
    item.click();
}
Uncaught TypeError: y.forEach is not a function
at i (<anonymous>:7:4)
at NodeList.forEach (<anonymous>)
at <anonymous>:3:3
Shayan
  • 709
  • 1
  • 15
  • 31
  • 1
    [`for...in`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...in) loops are for iterating over properties of an object. To iterate over items in an array use a [`for...of`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of) loop. BUT, [`NodeList`s](https://developer.mozilla.org/en-US/docs/Web/API/NodeList) are array-_like_, not actual arrays, and can't be treated exactly the same. To make an array of a `NodeList` use [`Array.from`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from). – Alexander Nied Oct 03 '19 at 14:02
  • I also tried for/of beforehand, it didn't work. I will try `Array.from` – Shayan Oct 03 '19 at 14:52
  • 1
    Right, `for...of` works on arrays and iterables but a `NodeList` is neither-- you would need to write it as `for(const someNode of Array.from(myNodeList)) { ...doStuff... }`. – Alexander Nied Oct 03 '19 at 15:10

2 Answers2

2

As you've figured it out with the children properties, the event listener is on li.toggle > details > summary, so you have to trigger click on that element. The easiest way to do that is:

var x = document.querySelectorAll('li.toggle details summary');
for(var i=0; i < x.length; i++) {
    x[i].click();
}

You can see that this code triggers the click event on every element in the sidebar, so not just closes the opened ones, but also opens the closed ones. However, when you open a menu, you can see that the <details> element gets an open attribute, so it becomes <details open>. If you target only these elements, you get your desired results:

var x = document.querySelectorAll('li.toggle details[open] summary');
for(var i=0; i < x.length; i++) {
    x[i].click();
}
frzsombor
  • 2,274
  • 1
  • 22
  • 40
1

Refer to this. for loop and html collections elements.

You should not use for in in html collections. Also in your first function alone you are trying to run forEach on a html collection of length 1 instead of on every item that you grab.

If you wanted to use a for of instead of the regular for loop just tweak what frzsombor wrote like so:

var x = document.querySelectorAll('li.toggle details summary');
for(let element of x) {
    element.click();
}
yoshinator
  • 436
  • 6
  • 13