Search code examples
javascriptcss-selectorsselectors-api

querySelector search immediate children


I have some jquery-like function:

function(elem) {
    return $('> someselector', elem);
};

The question is how can i do the same with querySelector()?

The problem is > selector in querySelector() requires parent to be explicitly specified. Is there any workaround?


Solution

  • Complete :scope polyfill

    As avetisk has mentioned Selectors API 2 uses :scope pseudo-selector.
    To make this work in all browsers (that support querySelector) here is the polyfill

    (function(doc, proto) {
      try { // check if browser supports :scope natively
        doc.querySelector(':scope body');
      } catch (err) { // polyfill native methods if it doesn't
        ['querySelector', 'querySelectorAll'].forEach(function(method) {
          var nativ = proto[method];
          proto[method] = function(selectors) {
            if (/(^|,)\s*:scope/.test(selectors)) { // only if selectors contains :scope
              var id = this.id; // remember current element id
              this.id = 'ID_' + Date.now(); // assign new unique id
              selectors = selectors.replace(/((^|,)\s*):scope/g, '$1#' + this.id); // replace :scope with #ID
              var result = doc[method](selectors);
              this.id = id; // restore previous id
              return result;
            } else {
              return nativ.call(this, selectors); // use native code for other selectors
            }
          }
        });
      }
    })(window.document, Element.prototype);
    

    Usage

    node.querySelector(':scope > someselector');
    node.querySelectorAll(':scope > someselector');
    

    For historical reasons, my previous solution

    Based on all answers

    // Caution! Prototype extending
    Node.prototype.find = function(selector) {
        if (/(^\s*|,\s*)>/.test(selector)) {
            if (!this.id) {
                this.id = 'ID_' + new Date().getTime();
                var removeId = true;
            }
            selector = selector.replace(/(^\s*|,\s*)>/g, '$1#' + this.id + ' >');
            var result = document.querySelectorAll(selector);
            if (removeId) {
                this.id = null;
            }
            return result;
        } else {
            return this.querySelectorAll(selector);
        }
    };
    

    Usage

    elem.find('> a');