Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Thoughts on creating unique selectors #3

Open
darcyclarke opened this issue Jun 4, 2015 · 2 comments
Open

Thoughts on creating unique selectors #3

darcyclarke opened this issue Jun 4, 2015 · 2 comments

Comments

@darcyclarke
Copy link
Member

@richgilbank you mentioned you may have something in the works for this. Would love a peak/insight. I know right now we store the HTMLElement Object, which isn't ideal.

Eventually, we'll need to do something like JSON.stringify( this.dssEvents ) and storing element objects wouldn't be great if we want the output to be pretty-printed for manual manipulation/storage. I think the best case scenario is to be able to store a selector string.

One strategy could be:

  1. Check for an id
  2. Fallback: Generate a selector for the element, based on its attributes and tagname, then find it's position relative to any other elements matching that selector (thus, creating a unique selector string)

I may mock this out if I have time but let me know your thoughts.

@darcyclarke
Copy link
Member Author

Okay... it's a bit rough around the edges but it seems to work (demo: http://jsfiddle.net/darcyclarke/gn3nwanc/15/)

// Generate A Unique Selector
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 + ')'; 

};

Probably needs more testing with nested elements to make sure the walker actually does its job to generate the right scoped selector... but yea... it seems to do the trick

@darcyclarke
Copy link
Member Author

@richgilbank does this look good/work?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant