JSFiddle - React, Tailwind, and code Playground

by darcyclarke

HTML

<div id="test"></div>
<div></div>
<div style="background-color: yellow;"></div>
<span></span>
<span class="box"></span>
<span class="box" data-num="3"></span>

CSS

body * {
    display: inline-block;
    width: 50px;
    height: 50px;
    background: red;
}

JavaScript

var els = document.querySelectorAll( 'div, span' );
els = Array.prototype.slice.call( els );
els.forEach( function( el ) {
    el.addEventListener( 'click', function( event ) {
        console.log( generateUniqeSelector( this ) );
    });
});

// Generate Selector By Tag + Attrs
var generateUniqeSelector = function ( el ) {
    
    var index;
    var siblings;
    var selector = '';
    var scopedSelector = '';
    var body = document.querySelector( 'body' );
    var tagName = el.tagName.toLowerCase();
    var parent = el.parentNode;    
    var attrs = (function( attrs ) {
        if ( attrs.length <= 0 ) {
            return '';
        }
        var str = '';
        attrs.forEach( function( attr ) { 
            str += '[' + attr.nodeName + '="' + attr.textContent + '"]'; 
        });
        return str;
    })( Array.prototype.slice.call( el.attributes ) );
    
    // Return if we have a unique selector
    if ( el.id ) {
       return '#' + el.id; 
    }
    
    // Return if we are dealing with body or html elements 
    if ( tagName === 'html' || tagName === 'body' ) {
        return tagName;   
    }
    
    // Return if tagname + attrs generates unique selector
    selector = tagName + attrs;
    siblings = document.querySelectorAll( selector ); 
    if ( siblings.length === 1 ) {
        return selector;        
    }

    // Return a truly unique selector using a scoped selector and index
    index = Array.prototype.indexOf.call( parent.children, el );
    while( parent != body ) {
        parent = parent.parentNode();   
        scopedSelector = parent.tagName.toLowerCase() + scopedSelector + ' ';
    }
    return 'body ' + scopedSelector + '*:nth-child(' + index + ')'; 
    
};