My FeedDiscussionsHeadless CMS
New
Sign in
Log inSign up
Learn more about Hashnode Headless CMSHashnode Headless CMS
Collaborate seamlessly with Hashnode Headless CMS for Enterprise.
Upgrade ✨Learn more
Avoid the Deprecated :scope Selector

Avoid the Deprecated :scope Selector

Emil Moe's photo
Emil Moe
·Sep 27, 2017

Yesterday while I was optimizing a development project to Internet Explorer, I realized that :scope is a deprecated keyword from all browsers and that it has never been supported by IE.

What is :scope

:scope lets your run a query selector, that takes the current element into the parameter string. For example

node.querySelector(':scope > div')

This would only find div that are direct children to node as I used scope.

Considerations

But since this isn't going to be working in IE I had to come up with another solution. Some solutions suggested prototype hacking to node.find() to make it look similar to jQuery. While I agree sometimes prototyping is okay, however in my opinion that is the case when it's adding new features for old browsers, such as polyfill.io.

The solution

My solution was to create a function, that generates a random ID for the node, if it doesn't have one, and remove it again. Thereby I can still select on it. I created 2 functions one for querySelector and one for querySelectorAll.

To use the function simply call find(document.querySelector('body'), 'div') to find all div that are direct children of body.

    /**
     * Find direct children to node, replicating .querySelector(':scope > [...]')
     */
    function find(node, selector) {
        removeId = false

        if (node.getAttribute('id') === null) {
            node.setAttribute('id', 'ID_' + new Date().getTime())
            removeId = true
        }

        let result = document.querySelector('#' + node.getAttribute('id') + ' > ' + selector)

        if (removeId)
            node.removeAttribute('id')

        return result
    }

    /**
     * Find direct children to node, replicating .querySelectorAll(':scope > [...]')
     */
    function findAll(node, selector) {
        removeId = false

        if (node.getAttribute('id') === null) {
            node.setAttribute('id', 'ID_' + new Date().getTime())
            removeId = true
        }

        let result = document.querySelectorAll('#' + node.getAttribute('id') + ' > ' + selector)

        if (removeId)
            node.removeAttribute('id')

        return result
    }