1. 4
  1.  

  2. 3

    The post says that css is broken, but the second example is a javascript api that just happens to use the same style of selectors than css.

    1. 2

      QUERYSELECTOR DOES NOT SCOPE TO THE ELEMENT

      Yeah, it does:

      The querySelector() method of the Element interface returns the first element that is a descendant of the element on which it is invoked that matches the specified group of selectors.

      https://developer.mozilla.org/Web/API/Element/querySelector

      Easy example. Go here: https://example.com. Result:

      document.querySelector('div').querySelector('div');
      null
      document.querySelector('div').querySelectorAll('div');
      NodeList []
      
      1. 4

        In a certain sense, it does, but not in the way you might expect it to.

        Suppose you have the following markup:

        <div class="a">
            <div class="b">
                <div class="c"></div>
            </div>
        </div>
        

        The result of b.querySelector('.a .c') is not document.querySelector('.b .a .c'), which would be null. Instead, it returns document.querySelectorAll('.a .c').filter(e => b.contains(e))[0] which is c.

        So it is scoped in the sense that you’ll only get back elements that are children of the element you’re calling querySelectorAll on, but the CSS query itself is not scoped to the element.

        1. 1

          Yeah, this tripped me up earlier in the year. I wrote a dom library for the D language and got a bug report saying the results were inconsistent with javascript and I was like “wtf”…. then saw this in the spec. (In fact, with mine, there’s just an implicit :scope at the start of the string, so you can do querySelector("> div"); to get like the immediate child.)

          I find my behavior more useful though so I haven’t actually “fixed” it… I actually don’t understand why javascript did it this way. It kinda smells like a bug that they regretted but couldn’t fix without unknowable compatibility woes, so they added :scope to work around it.

          1. 1

            Wow that is horrible. With the current page we are on, this fails:

            document.querySelector('.story').querySelector('.stories');
            

            but this works:

            document.querySelector('.story').querySelector('.stories .story_liner');
            
          2. 1

            I don’t know what to tell you, the code is there, and when run, you can see for yourself… https://jsfiddle.net/tyg2fdmp/

          3. 2

            Huh, the scoping behavior is genuinely new to me, thanks for sharing! I wonder how on Earth it has eluded me all this time.

            A bit of research:

            The behavior is explicitly described as early as 2008, although previous iterations already seemed to imply it.

            The behavior of querySelector / querySelectorAll also seems to have been the subject of lively discussion on the W3C mailing list, if anyone else is curious to dig into the history.

            Another piece of trivia I learned today: they’re named query... rather than get... to let you know querySelectorAll returns a static NodeList, whereas getElementsByTagName etc return live NodeLists — a distinction that doesn’t seem to have thrived in common awareness the way it was intended.