1

When you inspect an element in Google Chrome you see something like this:

html body div #content #mainbar form#post-form.post-form div#question-form div#post-editor.post-editor div div.wmd-containier ... span

html body div #content #mainbar form#post-form.post-form div#question-form div#post-editor.post-editor div div.wmd-containier ... span

Is there a method or a solution in jQuery that displays the same string for any object?

Rory McCrossan
  • 331,213
  • 40
  • 305
  • 339
Haradzieniec
  • 9,086
  • 31
  • 117
  • 212
  • 5
    So you mean the full CSS selector starting from the root element? Because "full DOM information" means something different entirely in actual DOM parlance. – BoltClock Jan 26 '15 at 11:35
  • 1
    Jquery as a Function for that -- http://api.jquery.com/parents/ – Luis Lopes Jan 26 '15 at 11:36
  • 1
    @Luis Lopes: That returns a collection of objects, not a string. You'd have to do some funky things with the collection in order to obtain a string. – BoltClock Jan 26 '15 at 11:37
  • @BoltClock nop - that returns a string :) check the examples he does a simple mapping on the elements you just need to change the mapping to whatever information you want. – Luis Lopes Jan 26 '15 at 11:38
  • @BoltClock Yes, I mean the full CSS selector - the line from the question as example would be fine. Now I started writing a function for that however I believe the nice solution exists already but I didn't find it. – Haradzieniec Jan 26 '15 at 11:39
  • 1
    @Luis Lopes: That's what I mean by "funky things". The function itself doesn't return a string. If it did, you wouldn't have to do *anything* beyond just calling it. – BoltClock Jan 26 '15 at 11:39
  • This will return parent of your elements: http://api.jquery.com/parent/ you may use a recursive function to call parents until you hit null, then print their class name or related attributes you want. – Soley Jan 26 '15 at 11:40
  • @BoltClock that doesnt look funky to me -- mby i am used to it.. it is very simple actually and clean. – Luis Lopes Jan 26 '15 at 11:41
  • @LuisLopes that is a very simplistic `map` implementation. What do you do in cases where elements have an id or class, or both, or neither? That's where the complications creep in. – Rory McCrossan Jan 26 '15 at 11:43
  • @RoryMcCrossan okay i am writing the answer -- i though this could be more easier to understand – Luis Lopes Jan 26 '15 at 11:44
  • For some reason i can write the answer.. Anyway check this file @RoryMcCrossan , Bolt and Haradzieniec: http://jsfiddle.net/ta9tbkgz/ – Luis Lopes Jan 26 '15 at 11:55
  • You may need to explain how this question is *not* a duplicate of: http://stackoverflow.com/questions/5728558/get-the-dom-path-of-the-clicked-a/5728626 – David Thomas Jan 26 '15 at 11:55

2 Answers2

2

Let's try and write one as a jQuery plugin - it should be trivial. All we need is to find the node's parents, and the node itself, and then generate a string containing the (lowercase) tag name, and (if supplied) the ID and classes:

(function($) {
    function tag(el) {
        var r = el.tagName.toLowerCase();
        if (el.id) {
            r += '#' + el.id;
        }
        if (el.className) {
            r += '.' + el.className.replace(/\s+/g, '.');
        }
        return r;
    }

    $.fn.path = function() {
        var node = this.get(0);    // in case multiple elements are passed
        return $(node).parents().add(node).get().map(tag).join(' ');
    }
})(jQuery);

Trying that out here on this stackoverflow page gives:

$('.vote').path()
> "html body.question-page.new-topbar div.container div#content.snippet-hidden 
   div div#mainbar div#question.question table tbody tr td.votecell div.vote"
Alnitak
  • 334,560
  • 70
  • 407
  • 495
  • 4
    "please don't vote till I confirm it's done" ***YOU CAN'T TELL ME WHAT TO DO!*** (you *could* delete it and edit it while it's deleted to block voting, but you could have just held off on posting it entirely until you're sure) – BoltClock Jan 26 '15 at 11:51
  • 1
    @BoltClock Fair enough, I just wanted to show evolution of this as a work in progress – Alnitak Jan 26 '15 at 11:56
  • important to note that this (*nor what the chrome tools show*) is not a uniquely identifying path. It could be matching multiple elements. (*chrome tools imply a `>` between each part of the selector, but still do not accound for sibling elements of the same type*) – Gabriele Petrioli Jan 26 '15 at 12:30
  • 1
    @GabyakaG.Petrioli that's a good point. I was also considering an option to insert the implicit `" > "` between each entry – Alnitak Jan 26 '15 at 12:57
2

This will create a selector with ids and class names, you may add more attribute detection in the map function:

var getSelector = function(t){
    var elements = [];
    while( t.parentNode ){
        elements.push( t );
        t = t.parentNode;
    }
    var selector = elements.reverse().map( function( elm ){
       var elementSelector = elm.nodeName.toLowerCase();
        if( elm.id ){
            elementSelector += '#' + elm.id
        }
        if( elm.className ){
            elementSelector += '.' + elm.className.split(/\s/).join('.')
        }
        selector += elementSelector;
        return elementSelector;
    }).join(' ');
    return selector;
}

http://jsfiddle.net/41dq3rbq/2/

pawel
  • 35,827
  • 7
  • 56
  • 53