Fidilip
Fidilip

Reputation: 1229

How can I get selector from jQuery object

$("*").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?

Upvotes: 122

Views: 121229

Answers (21)

oyosoftware
oyosoftware

Reputation: 21

Almost perfect, except: If you used text as an argument, you don't need this snippet, because you already know. But.. if you used an object as an argument, you want to know the original argument. So a little more code. If this is the case, the selector is already set by a previous function, so all you have to do is get the selector of the selector!!! (huh?). You only can't use the null value, because that is an object too. Let's see:

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

To make it complete, you can also use the context from the second argument and put it in front of the selector:

$ = (function(jQ) { 
    return (function() { 
        var fnc = jQ.apply(this,arguments);
        fnc.selector = (arguments.length>0)?arguments[0]:undefined;
        fnc.context = (arguments.length>1)?arguments[1]:undefined;
        if (typeof fnc.selector === "object") {
            fnc.context = fnc.selector.context;
            fnc.selector = fnc.selector.selector;
        }
        if (fnc.context !== undefined) {
            fnc.selector = fnc.context + " " + fnc.selector;
        }
        if (fnc.selector === undefined) {
            delete fnc.selector;
        }
        delete fnc.context;
        return fnc; 
    });
})($);

However... the code destroys all jQuery functions. Reason: a new jQuery object replaces the original $ object.

In the meantime I dicovered a new way, by extending jQuery.

$.fn.extend({
    initConstructor: $.fn.init,
    init: function (selector, context, rootjQuery) {
        var obj = new $.fn.initConstructor(selector, context, rootjQuery);
        if (selector !== undefined) {
            obj.selector = selector;
            if (obj.selector.selector !== undefined) {
                obj.selector = obj.selector.selector;
            }
        }
        return obj;
    }
});

This code can be used inside as well outside the ready context. Also you can expand this code for the context argument.

Upvotes: 0

Sejal Varu
Sejal Varu

Reputation: 54

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>

Upvotes: 0

Patrick
Patrick

Reputation: 31

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);

Upvotes: 0

Anny
Anny

Reputation: 1

The best answer would be

var selector = '#something';

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

Upvotes: -8

Albert Horta
Albert Horta

Reputation: 51

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.

Upvotes: 5

Codemole
Codemole

Reputation: 3189

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;
}

Upvotes: 1

Vivek Kumar
Vivek Kumar

Reputation: 2889

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;

});

Upvotes: 1

Nick Humphrey
Nick Humphrey

Reputation: 611

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

Upvotes: -1

AmazingDayToday
AmazingDayToday

Reputation: 4272

Try this:

$("*").click(function(event){
    console.log($(event.handleObj.selector));
 });

Upvotes: 3

p1nox
p1nox

Reputation: 623

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?

Upvotes: 1

Azghanvi
Azghanvi

Reputation: 964

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;
}

Upvotes: 1

jessegavin
jessegavin

Reputation: 75640

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

Upvotes: 60

Anurag
Anurag

Reputation: 141869

::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().

Upvotes: 35

Will
Will

Reputation: 7245

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/

Upvotes: 22

ngs
ngs

Reputation: 59

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

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

Upvotes: 1

jaipster
jaipster

Reputation: 11997

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>

Upvotes: 0

abhilashv
abhilashv

Reputation: 1482

Did you try this ?

 $("*").click(function(){
    $(this).attr("id"); 
 });

Upvotes: 5

Dustin
Dustin

Reputation: 1026

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;
}

Upvotes: 1

Paul Irish
Paul Irish

Reputation: 49142

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. :)

Upvotes: 1

Dean Harding
Dean Harding

Reputation: 72658

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?
});

Upvotes: -4

jessegavin
jessegavin

Reputation: 75640

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 *.

Upvotes: 0

Related Questions