120
$("*").click(function(){
    $(this); // how can I get selector from $(this) ?
});

Is there an easy way to get selector from $(this)? There is a way to select an element by its selector, but what about getting the selector from element?

Cœur
  • 37,241
  • 25
  • 195
  • 267
Fidilip
  • 1,209
  • 2
  • 9
  • 3
  • Just curious why this would be useful? What you're saying here (semantically) is for every element referenced as $(this)... the element itself is $(this) thus the selector is not required. You've got the object... – BenAlabaster Mar 10 '10 at 22:07
  • 1
    you DO realize that the click with nested elements will return more than one? div in a body, etc. or am I too tired at this juncture? – Mark Schultheiss Mar 10 '10 at 22:11
  • 2
    It would be helpful if you could describe the 'end goal' of what you're trying to accomplish. You might get better help that way. – jessegavin Mar 10 '10 at 22:13
  • 3
    An element can be *selected* in a myriad of different ways. Also, selector !== path. What do you expect to do with this information? – deceze Mar 10 '10 at 23:15
  • I agree with deceze on the selector !== path. You might have a UL tag with three LI tags nested inside of it. They will all have the same path. – jessegavin Mar 10 '10 at 23:22
  • Downvoted because I'm not sure what you're asking. You want to be able to consult the jQuery object wrapping `this` for the information that it came about by a selector of `"*"`. In fact the jQuery object constructed by wrapping `this` is a separate one to what was constructed by selecting `"*"`. – hippietrail Oct 17 '12 at 10:25
  • In my case I have to process result of $(":focus"). I am not sure whether focused element has class or id or any other identification – Jan Stanicek Oct 12 '16 at 15:10
  • 3
    This can be useful if you already found a JQuery element, and are using a plugin/module/subroutine, that requires a selector to work (possibly out of your control). – Andy Dec 20 '16 at 23:59

20 Answers20

59

Ok, so in a comment above the question asker Fidilip said that what he/she's really after is to get the path to the current element.

Here's a script that will "climb" the DOM ancestor tree and then build fairly specific selector including any id or class attributes on the item clicked.

See it working on jsFiddle: http://jsfiddle.net/Jkj2n/209/

<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<script>
    $(function() {
        $("*").on("click", function(e) {
          e.preventDefault();
          var selector = $(this)
            .parents()
            .map(function() { return this.tagName; })
            .get()
            .reverse()
            .concat([this.nodeName])
            .join(">");

          var id = $(this).attr("id");
          if (id) { 
            selector += "#"+ id;
          }

          var classNames = $(this).attr("class");
          if (classNames) {
            selector += "." + $.trim(classNames).replace(/\s/gi, ".");
          }

          alert(selector);
      });
    });
    </script>
</head>
<body>
<h1><span>I love</span> jQuery</h1>
<div>
  <p>It's the <strong>BEST THING</strong> ever</p>
  <button id="myButton">Button test</button>
</div>
<ul>
  <li>Item one
    <ul>
      <li id="sub2" >Sub one</li>
      <li id="sub2" class="subitem otherclass">Sub two</li>
    </ul>
  </li>
</ul>
</body>
</html>

For example, if you were to click the 2nd list nested list item in the HTML below, you would get the following result:

HTML>BODY>UL>LI>UL>LI#sub2.subitem.otherclass

jessegavin
  • 74,067
  • 28
  • 136
  • 164
  • 2
    Thanks! I'll use your code with one modification on the join... `join(" > ");`, will get me the immediate children and hence a more *strict* path. – nonsensickle Jun 18 '14 at 06:19
  • FANTASTIC...am gonna use it for my chrome extension. Just one thing, sometime id is used with colon ':' prefixed, which we can replace with '\\:' – Savaratkar Jun 23 '15 at 11:48
  • Good call @nonsensickle. I updated my example, and removed an if statement too. – jessegavin Jun 23 '15 at 16:12
  • The code fragment above doesn't return classes for SVG objects. Here is a jsFiddle that works for SVG: [http://jsfiddle.net/mikemsq/vbykja4x/7/](http://jsfiddle.net/mikemsq/vbykja4x/7/). – mikemsq Aug 08 '19 at 18:39
  • @nonsensickle, the white space is optional: https://w3c.github.io/csswg-drafts/selectors/#child-combinators – jrdioko Feb 06 '23 at 17:23
35

::WARNING::
.selector has been deprecated as of version 1.7, removed as of 1.9

The jQuery object has a selector property I saw when digging in its code yesterday. Don't know if it's defined in the docs are how reliable it is (for future proofing). But it works!

$('*').selector // returns *

Edit: If you were to find the selector inside the event, that information should ideally be part of the event itself and not the element because an element could have multiple click events assigned through various selectors. A solution would be to use a wrapper to around bind(), click() etc. to add events instead of adding it directly.

jQuery.fn.addEvent = function(type, handler) {
    this.bind(type, {'selector': this.selector}, handler);
};

The selector is being passed as an object's property named selector. Access it as event.data.selector.

Let's try it on some markup (http://jsfiddle.net/DFh7z/):

<p class='info'>some text and <a>a link</a></p>​

$('p a').addEvent('click', function(event) {
    alert(event.data.selector); // p a
});

Disclaimer: Remember that just as with live() events, the selector property may be invalid if DOM traversal methods are used.

<div><a>a link</a></div>

The code below will NOT work, as live relies on the selector property which in this case is a.parent() - an invalid selector.

$('a').parent().live(function() { alert('something'); });

Our addEvent method will fire, but you too will see the wrong selector - a.parent().

Brett Weber
  • 1,839
  • 18
  • 22
Anurag
  • 140,337
  • 36
  • 221
  • 257
  • I think this is the best what we cen get from jquery =). Maybe i'll find full solution later. Anyway this can be really handy, thx! =) – Fidilip Mar 10 '10 at 22:46
  • @MarkoDumic: Must've been deprecated. The link is now dead and following it tells us only: `No Such jQuery Method Exists` – hippietrail Oct 17 '12 at 10:21
  • 13
    @Levitikon Are you really downvoting an answer three years old because now it is deprecated?! You should indeed edit answer and put a warning – A. Wolff May 20 '14 at 15:37
22

In collaboration with @drzaus we've come up with the following jQuery plugin.

jQuery.getSelector

!(function ($, undefined) {
    /// adapted http://jsfiddle.net/drzaus/Hgjfh/5/

    var get_selector = function (element) {
        var pieces = [];

        for (; element && element.tagName !== undefined; element = element.parentNode) {
            if (element.className) {
                var classes = element.className.split(' ');
                for (var i in classes) {
                    if (classes.hasOwnProperty(i) && classes[i]) {
                        pieces.unshift(classes[i]);
                        pieces.unshift('.');
                    }
                }
            }
            if (element.id && !/\s/.test(element.id)) {
                pieces.unshift(element.id);
                pieces.unshift('#');
            }
            pieces.unshift(element.tagName);
            pieces.unshift(' > ');
        }

        return pieces.slice(1).join('');
    };

    $.fn.getSelector = function (only_one) {
        if (true === only_one) {
            return get_selector(this[0]);
        } else {
            return $.map(this, function (el) {
                return get_selector(el);
            });
        }
    };

})(window.jQuery);

Minified Javascript

// http://stackoverflow.com/questions/2420970/how-can-i-get-selector-from-jquery-object/15623322#15623322
!function(e,t){var n=function(e){var n=[];for(;e&&e.tagName!==t;e=e.parentNode){if(e.className){var r=e.className.split(" ");for(var i in r){if(r.hasOwnProperty(i)&&r[i]){n.unshift(r[i]);n.unshift(".")}}}if(e.id&&!/\s/.test(e.id)){n.unshift(e.id);n.unshift("#")}n.unshift(e.tagName);n.unshift(" > ")}return n.slice(1).join("")};e.fn.getSelector=function(t){if(true===t){return n(this[0])}else{return e.map(this,function(e){return n(e)})}}}(window.jQuery)

Usage and Gotchas

<html>
    <head>...</head>
    <body>
        <div id="sidebar">
            <ul>
                <li>
                    <a href="/" id="home">Home</a>
                </li>
            </ul>
        </div>
        <div id="main">
            <h1 id="title">Welcome</h1>
        </div>

        <script type="text/javascript">

            // Simple use case
            $('#main').getSelector();           // => 'HTML > BODY > DIV#main'

            // If there are multiple matches then an array will be returned
            $('body > div').getSelector();      // => ['HTML > BODY > DIV#main', 'HTML > BODY > DIV#sidebar']

            // Passing true to the method will cause it to return the selector for the first match
            $('body > div').getSelector(true);  // => 'HTML > BODY > DIV#main'

        </script>
    </body>
</html>

Fiddle w/ QUnit tests

http://jsfiddle.net/CALY5/5/

Will
  • 7,225
  • 2
  • 23
  • 14
  • I liked where you were going, so I made some [fixes/changes](http://jsfiddle.net/drzaus/Hgjfh/4/): * jQuery plugin leverages jQuery utility `$.map` * optional delimiter (needs to strip weird empty tagNames) * don't you need to check `hasOwnProperty` in a `foreach` loop to be safe? – drzaus Mar 29 '13 at 14:26
  • Thanks for the comments, I'll set up a proper test suite in a fiddle this weekend and work on incorporating your suggestions. – Will Mar 29 '13 at 15:02
  • 1
    @drzaus I've updated the question. I decided to leave out the custom delimiter you added since any delimiter other than `' > '` would cause it to not return the element's selector. – Will Mar 30 '13 at 01:27
  • cool, nice work; hadn't seen qunit before. i figured the delimiter was just for presentation, but now i get that it's part of the literal selector path. – drzaus Apr 02 '13 at 13:47
5

Did you try this ?

 $("*").click(function(){
    $(this).attr("id"); 
 });
Leniel Maccaferri
  • 100,159
  • 46
  • 371
  • 480
abhilashv
  • 1,418
  • 1
  • 13
  • 18
3

Try this:

$("*").click(function(event){
    console.log($(event.handleObj.selector));
 });
AmazingDayToday
  • 3,724
  • 14
  • 35
  • 67
3

Just add a layer over the $ function this way:

$ = (function(jQ) { 
 return (function() { 
  var fnc = jQ.apply(this,arguments);
  fnc.selector = (arguments.length>0)?arguments[0]:null;
  return fnc; 
 });
})($);

Now you can do things like

$("a").selector
and will return "a" even on newer jQuery versions.
  • This does exactly what I wanted. It works suspiciously well given how long I've looked for this! Thank you Albert. – Mark Notton Jan 28 '19 at 14:46
1

I added some fixes to @jessegavin's fix.

This will return right away if there is an ID on the element. I also added a name attribute check and a nth-child selector in case a element has no id, class, or name.

The name might need scoping in case there a multiple forms on the page and have similar inputs, but I didn't handle that yet.

function getSelector(el){
    var $el = $(el);

    var id = $el.attr("id");
    if (id) { //"should" only be one of these if theres an ID
        return "#"+ id;
    }

    var selector = $el.parents()
                .map(function() { return this.tagName; })
                .get().reverse().join(" ");

    if (selector) {
        selector += " "+ $el[0].nodeName;
    }

    var classNames = $el.attr("class");
    if (classNames) {
        selector += "." + $.trim(classNames).replace(/\s/gi, ".");
    }

    var name = $el.attr('name');
    if (name) {
        selector += "[name='" + name + "']";
    }
    if (!name){
        var index = $el.index();
        if (index) {
            index = index + 1;
            selector += ":nth-child(" + index + ")";
        }
    }
    return selector;
}
Dustin
  • 966
  • 8
  • 15
1

I've released a jQuery plugin: jQuery Selectorator, you can get selector like this.

$("*").on("click", function(){
  alert($(this).getSelector().join("\n"));
  return false;
});
ngs
  • 59
  • 4
1

I was getting multiple elements even after above solutions, so i extended dds1024 work, for even more pin-pointing dom element.

e.g. DIV:nth-child(1) DIV:nth-child(3) DIV:nth-child(1) ARTICLE:nth-child(1) DIV:nth-child(1) DIV:nth-child(8) DIV:nth-child(2) DIV:nth-child(1) DIV:nth-child(2) DIV:nth-child(1) H4:nth-child(2)

Code:

function getSelector(el)
{
    var $el = jQuery(el);

    var selector = $el.parents(":not(html,body)")
                .map(function() { 
                                    var i = jQuery(this).index(); 
                                    i_str = ''; 

                                    if (typeof i != 'undefined') 
                                    {
                                        i = i + 1;
                                        i_str += ":nth-child(" + i + ")";
                                    }

                                    return this.tagName + i_str; 
                                })
                .get().reverse().join(" ");

    if (selector) {
        selector += " "+ $el[0].nodeName;
    }

    var index = $el.index();
    if (typeof index != 'undefined')  {
        index = index + 1;
        selector += ":nth-child(" + index + ")";
    }

    return selector;
}
Azghanvi
  • 934
  • 10
  • 22
1

Taking in account some answers read here I'd like to propose this:

function getSelectorFromElement($el) {
  if (!$el || !$el.length) {
    return ;
  }

  function _getChildSelector(index) {
    if (typeof index === 'undefined') {
      return '';
    }

    index = index + 1;
    return ':nth-child(' + index + ')';
  }

  function _getIdAndClassNames($el) {
    var selector = '';

    // attach id if exists
    var elId = $el.attr('id');
    if(elId){
      selector += '#' + elId;
    }

    // attach class names if exists
    var classNames = $el.attr('class');
    if(classNames){
      selector += '.' + classNames.replace(/^\s+|\s+$/g, '').replace(/\s/gi, '.');
    }

    return selector;
  }

  // get all parents siblings index and element's tag name,
  // except html and body elements
  var selector = $el.parents(':not(html,body)')
    .map(function() {
      var parentIndex = $(this).index();

      return this.tagName + _getChildSelector(parentIndex);
    })
    .get()
    .reverse()
    .join(' ');

  if (selector) {
    // get node name from the element itself
    selector += ' ' + $el[0].nodeName +
      // get child selector from element ifself
      _getChildSelector($el.index());
  }

  selector += _getIdAndClassNames($el);

  return selector;
}

Maybe useful to create a jQuery plugin?

p1nox
  • 623
  • 1
  • 7
  • 13
  • After 5 years. I have used it in Cypress - page object model. Taking note here if someone else needs to have the selector of Cypress.Chaniable object. Just the $(this) should be replaced with Cypress.$(this) then the rest is all fine. – celoaga Sep 10 '21 at 09:27
1

This can get you selector path of clicked HTML element-

 $("*").on("click", function() {

    let selectorPath = $(this).parents().map(function () {return this.tagName;}).get().reverse().join("->");

    alert(selectorPath);

    return false;

});
Vivek Kumar
  • 2,625
  • 2
  • 25
  • 33
1

Well, I wrote this simple jQuery plugin.

This checkes id or class name, and try to give as much exact selector as possible.

jQuery.fn.getSelector = function() {

    if ($(this).attr('id')) {
        return '#' + $(this).attr('id');
    }

    if ($(this).prop("tagName").toLowerCase() == 'body')    return 'body';

    var myOwn = $(this).attr('class');
    if (!myOwn) {
        myOwn = '>' + $(this).prop("tagName");
    } else {
        myOwn = '.' + myOwn.split(' ').join('.');
    }

    return $(this).parent().getSelector() + ' ' + myOwn;
}
Codemole
  • 3,069
  • 5
  • 25
  • 41
1

http://www.selectorgadget.com/ is a bookmarklet designed explicitly for this use case.

That said, I agree with most other people in that you should just learn CSS selectors yourself, trying to generate them with code is not sustainable. :)

Paul Irish
  • 47,354
  • 22
  • 98
  • 132
0

Javascript code for the same, in case any one needs, as i needed it. This just the translation only of the above selected answer.

    <script type="text/javascript">

function getAllParents(element){
    var a = element;
    var els = [];
    while (a && a.nodeName != "#document") {
        els.unshift(a.nodeName);
        a = a.parentNode;
    }
    return els.join(" ");
}

function getJquerySelector(element){

    var selector = getAllParents(element);
    /* if(selector){
        selector += " " + element.nodeName;
    } */
    var id = element.getAttribute("id");
    if(id){
        selector += "#" + id;
    }
    var classNames = element.getAttribute("class");
    if(classNames){
        selector += "." + classNames.replace(/^\s+|\s+$/g, '').replace(/\s/gi, ".");
    }
    console.log(selector);
    alert(selector);
    return selector;
}
</script>
jaipster
  • 11,967
  • 2
  • 21
  • 24
0

Are you trying to get the name of the current tag that was clicked?

If so, do this..

$("*").click(function(){
    alert($(this)[0].nodeName);
});

You can't really get the "selector", the "selector" in your case is *.

jessegavin
  • 74,067
  • 28
  • 136
  • 164
  • I dont need the tag name. I need just path to the element i clicked. – Fidilip Mar 10 '10 at 22:15
  • 1
    AH, starting to get somewhere "path to the element" is much different than "selector". SO you need the element, and all its parents node names? – Mark Schultheiss Mar 10 '10 at 22:48
  • I have posted another answer which gets more towards your actual goal. You should edit the question so that it is more specific. – jessegavin Mar 10 '10 at 23:11
0

Thank you p1nox!

My problem was to put focus back on an ajax call that was modifying part of the form.

$.ajax({  url : "ajax_invite_load.php",
        async : true,
         type : 'POST',
         data : ...
     dataType : 'html',
      success : function(html, statut) {
                    var focus = $(document.activeElement).getSelector();
                    $td_left.html(html);
                    $(focus).focus();
                }
});

I just needed to encapsulate your function in a jQuery plugin:

    !(function ($, undefined) {

    $.fn.getSelector = function () {
      if (!this || !this.length) {
        return ;
      }

      function _getChildSelector(index) {
        if (typeof index === 'undefined') {
          return '';
        }

        index = index + 1;
        return ':nth-child(' + index + ')';
      }

      function _getIdAndClassNames($el) {
        var selector = '';

        // attach id if exists
        var elId = $el.attr('id');
        if(elId){
          selector += '#' + elId;
        }

        // attach class names if exists
        var classNames = $el.attr('class');
        if(classNames){
          selector += '.' + classNames.replace(/^\s+|\s+$/g, '').replace(/\s/gi, '.');
        }

        return selector;
      }

      // get all parents siblings index and element's tag name,
      // except html and body elements
      var selector = this.parents(':not(html,body)')
        .map(function() {
          var parentIndex = $(this).index();

          return this.tagName + _getChildSelector(parentIndex);
        })
        .get()
        .reverse()
        .join(' ');

      if (selector) {
        // get node name from the element itself
        selector += ' ' + this[0].nodeName +
          // get child selector from element ifself
          _getChildSelector(this.index());
      }

      selector += _getIdAndClassNames(this);

      return selector;
    }

})(window.jQuery);
Patrick
  • 31
  • 2
0

Select Elements by Name :

$('p').append('This is paragraph.'); // appends text to all p elements  
$('div').append('This is div.); 

<div>
    <p></p>
    <p></p>
</div>

Select Elements by Id:

$('#impPrg').append('This element\'s id is "impPrg"');   
<p id="impPrg"></p>
Sejal Varu
  • 22
  • 6
-1

This won't show you the DOM path, but it will output a string representation of what you see in eg chrome debugger, when viewing an object.

$('.mybtn').click( function(event){
    console.log("%s", this);    // output: "button.mybtn"
});

https://developer.chrome.com/devtools/docs/console-api#consolelogobject-object

Nick Humphrey
  • 611
  • 6
  • 15
-4

How about:

var selector = "*"
$(selector).click(function() {
    alert(selector);
});

I don't believe jQuery store the selector text that was used. After all, how would that work if you did something like this:

$("div").find("a").click(function() {
    // what would expect the 'selector' to be here?
});
Dean Harding
  • 71,468
  • 13
  • 145
  • 180
  • jQuery internally builds the selector `$('div').find('a').selector` is `div a`. If the events are not created through the jQuery functions, but a wrapper instead, I believe the selector could be passed as the data arguments to the event handler. – Anurag Mar 10 '10 at 23:23
  • 1
    Is this actually a serious answer? – Glen Mar 28 '18 at 08:57
-8

The best answer would be

var selector = '#something';

$(selector).anything(function(){
  console.log(selector);
});
Anny
  • 1