'Create new element from selector?

How can I create a new element using just a selector? (e.g. .myclass, #myid or a:not(.someclass)) Basically there is no way for you to tell if the element is a div, span, li, an anchor, if it's a div with a class or with an id and so on.

In jQuery I know you can do $(selector) to get a usable DOM object. But how can this be done in JavaScript?



Solution 1:[1]

In jQuery I know you can do $(selector) to get a usable DOM object...

Not to create one. jQuery will do a search in the DOM for existing matches. You can do $("<div>") and such (note that's HTML, not a CSS selector) to create elements, but jQuery doesn't have a feature for creating elements from CSS selectors.

But how can this be done in JavaScript?

You'll have to parse the selector, and then use document.createElement with the tag name, and then set any classes or other things the selector describes on the new element.

CSS selectors aren't very hard to parse. You'll be able to find a lib that does it. (jQuery has Sizzle, which is a selector engine, built in and Sizzle is open source. It will naturally have code to parse selectors.)

Solution 2:[2]

Mootools does this.

new Element('#name.class')

yields

<div id=?"name" class=?"class">?</div>?

Solution 3:[3]

The answer appears to be that there is no built-in way of doing this. Maybe there’s a library which does the job.

However, it’s not to hard to write a function to create an element from a simple selector:

/*  createElementFromSelector(selector)
    ================================================
    Usage: element#id.class@attribute=value
    ================================================ */

    function createElementFromSelector(selector) {
        var pattern = /^(.*?)(?:#(.*?))?(?:\.(.*?))?(?:@(.*?)(?:=(.*?))?)?$/;
        var matches = selector.match(pattern);
        var element = document.createElement(matches[1]||'div');
        if(matches[2]) element.id = matches[2];
        if(matches[3]) element.className = matches[3];
        if(matches[4]) element.setAttribute(matches[4],matches[5]||'');
        return element;
    }
    
    var testitems = [
        'div#id.class@attribute=value',
        'div#id.class@attribute',
        'div',
        'div#id',
        'div.class',
        '#id',
        '.class',
        '#id.class',
        '@whatever'
    ];
    
    testitems.forEach(item => {
        var element = createElementFromSelector(item);
        console.log(element);
    });

The tricky part is the regular expression. You can see it in detail here: https://regex101.com/r/ASREb0/1 .

The function only accepts selectors in the form element#id.class@attribute=value with the any of components being optional, as you see in the test items. I think including pseudo classes is probably pushing the friendship, but you might like to modify it to include multiple real classes.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 T.J. Crowder
Solution 2 Lodewijk
Solution 3