4

I am trying to hide the comments with the children like reddit, and I wrote this function:

function toggle(id, lft, rgt) {
    var kids = (rgt - lft - 1) / 2;
    if (kids >= 1) {
        var element = document.querySelector("div.com#com" + id).getAttribute('value');
        var low = Number(element.split('-')[0]);
        var high = Number(element.split('-')[1]);
        for (var i = low + 1; i <= high - 1; i += 1) {
            const x = document.querySelectorAll('div.com[min=' + i + ']');
        }
        Array.from(x).forEach(comment => {
            if (comment.style.display === "none") {
                comment.style.display = "block";
            } else {
                comment.style.display = "none";
            }
        });
    }

for example this is the parent comment:

<div> 
      <a onclick="return toggle(1, 1, 4)" href="javascript:void(0)">[-]</a>
       <div id="com1" class="com md" value="1-4" min="1">yellow</div>
</div> 

and this is a child comment:

<div> 
     <a onclick="return toggle(2, 2, 3)" href="javascript:void(0)">[-]</a>
    <div id="com2" class="com md" value="2-3" min="2">hello </div>
</div> 

I want to hide all the comments that have the min attribute between the parent value 1 and 4 and this child have the min=2 so it must be hidden. BUT the js function isn't working, so what's the problem?

other questions?

  • Should I write the foreach inside the for loop or it's fine like this way?
  • if the error in the title is fixed, will the function work and the child comments will be hidden, if not, why?
xxx
  • 1,153
  • 1
  • 11
  • 23
lawlawi
  • 47
  • 1
  • 6
  • 1
    Why use class selectors when you have what is supposed to be a unique ID? Just use `document.getElementById("com"+id).getAttribute("value")` - however using a value attribute on a non form field is not recommended – mplungjan Jun 13 '19 at 13:22
  • Also please click [edit](https://stackoverflow.com/posts/56581472/edit) then `[<>]` snippet editor and produce a [mcve] – mplungjan Jun 13 '19 at 13:26
  • @mplungjan thanks, but the problem is in `const x = document.querySelectorAll('div.com[min=' + i + ']'); ` – lawlawi Jun 13 '19 at 13:31
  • 1
    No don't. @mplungjan the difference between 'div.com[min=' + i + ']` and `div.com[min="${i}"]` is that the first will generate `'div.com[min=0]'` which is invalid, while the second will generate `'div.com[min="0"]'` which is valid? Also, this question is a good sign post, people may very well come here with the same DOMException error message (minus the actual `'div.com[min=]'` past) – Kaiido Jun 13 '19 at 13:48
  • Because of the numeric? – mplungjan Jun 13 '19 at 13:49
  • Yes, non-quoted attributes can't start by a digit. – Kaiido Jun 13 '19 at 13:50
  • Not do what? The solution is to wrap the attribute value in quotation marks, as the accepted answer states, and as the dupe answers explain. – Kaiido Jun 13 '19 at 13:51
  • 1
    Also the for loop makes no sense..... you are only doing the Array.from() on the last item in the collection. – epascarello Jun 13 '19 at 13:52
  • @mplungjan what about ? – Kaiido Jun 13 '19 at 13:53

1 Answers1

4

Well, as the error message says, your selector is invalid. Add quotation marks around the value of the attribute.

const x = document.querySelectorAll(`div.com[min="${i}"]`);

(It looks more readable with ES6 template literals).

Kaiido
  • 123,334
  • 13
  • 219
  • 285
mbojko
  • 13,503
  • 1
  • 16
  • 26
  • THANKS A LOT @mbojko, that worked, and the function didn't work but then I copied the `foreach ` inside the `for loop` and it worked. THANKS A LOT – lawlawi Jun 13 '19 at 13:37
  • I found a strange behaviour with this, where some values generated this error and some didn't. I didn't manage to pin down exactly what aspect made the difference. Putting single quotes around the value fixes it in all cases. – Max Williams Jun 14 '22 at 17:29