Wie kann ich einen Selektor vom jQuery-Objekt erhalten?

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

Gibt es eine einfache Möglichkeit, einen Selektor$(this) zu erhalten ? Es gibt eine Möglichkeit, ein Element anhand seines Selektors auszuwählen, aber wie sieht es aus , wenn der Selektor vom Element abgerufen wird ?

Fidilip
quelle
Nur neugierig, warum das nützlich wäre? Was Sie hier (semantisch) sagen, gilt für jedes Element, das als $ (this) bezeichnet wird ... das Element selbst ist $ (this), daher ist der Selektor nicht erforderlich. Sie haben das Objekt ...
BenAlabaster
1
Sie wissen, dass der Klick mit verschachtelten Elementen mehr als eins zurückgibt? Div in einem Körper usw. oder bin ich zu diesem Zeitpunkt zu müde?
Mark Schultheiss
2
Es wäre hilfreich, wenn Sie das „Endziel“ dessen beschreiben könnten, was Sie erreichen möchten. Auf diese Weise erhalten Sie möglicherweise bessere Hilfe.
Jessegavin
3
Ein Element kann auf vielfältige Weise ausgewählt werden. Auch Selektor! == Pfad. Was erwarten Sie mit diesen Informationen?
Täuschung
2
Dies kann nützlich sein, wenn Sie bereits ein JQuery-Element gefunden haben und ein Plugin / Modul / Unterprogramm verwenden, für dessen Funktion ein Selektor erforderlich ist (möglicherweise außerhalb Ihrer Kontrolle).
Andy

Antworten:

57

Ok, also Fidilipsagte der Fragesteller in einem Kommentar oben , dass er / sie wirklich danach strebt , den Weg zum aktuellen Element zu finden.

Hier ist ein Skript, das den DOM-Ahnenbaum "klettert" und dann einen ziemlich spezifischen Selektor erstellt, einschließlich eines idoder classmehrerer Attribute für das angeklickte Element.

Sehen Sie, wie es auf jsFiddle funktioniert: 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>

Wenn Sie beispielsweise auf das zweite Listenelement mit verschachtelter Liste im folgenden HTML-Code klicken, erhalten Sie das folgende Ergebnis:

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

Jessegavin
quelle
2
Vielen Dank! Ich werde Ihren Code mit einer Änderung auf dem Join verwenden ... join(" > ");, wird mir die unmittelbaren Kinder und damit einen strengeren Pfad geben.
unsinnig
FANTASTISCH ... werde es für meine Chrome-Erweiterung verwenden. Nur eine Sache, manchmal wird id mit dem vorangestellten Doppelpunkt ':' verwendet, den wir durch '\\:' ersetzen können
Savaratkar
Guter Anruf @nonsensickle. Ich habe mein Beispiel aktualisiert und auch eine if-Anweisung entfernt.
Jessegavin
Das obige Codefragment gibt keine Klassen für SVG-Objekte zurück. Hier ist eine jsFiddle, die für SVG funktioniert: http://jsfiddle.net/mikemsq/vbykja4x/7/ .
Mikemsq
32

::
WARNUNG :: .selector ist ab Version 1.7 veraltet und ab Version 1.9 entfernt

Das jQuery-Objekt hat eine Selector-Eigenschaft, die ich gestern beim Eingraben seines Codes gesehen habe. Ich weiß nicht, ob es in den Dokumenten definiert ist, wie zuverlässig es ist (für die Zukunftssicherung). Aber es funktioniert!

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

Bearbeiten : Wenn Sie den Selektor innerhalb des Ereignisses finden, sollten diese Informationen idealerweise Teil des Ereignisses selbst und nicht des Elements sein, da einem Element mehrere Klickereignisse über verschiedene Selektoren zugewiesen werden können. Eine Lösung wäre, einen Wrapper zu verwenden bind(), click()um Ereignisse usw. hinzuzufügen, anstatt sie direkt hinzuzufügen.

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

Der Selektor wird als Eigenschaft eines Objekts mit dem Namen übergeben selector. Greifen Sie als zu event.data.selector.

Versuchen wir es mit einem 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
});

Haftungsausschluss : Beachten Sie, dass live()die Selector-Eigenschaft genau wie bei Ereignissen ungültig sein kann, wenn DOM-Traversal-Methoden verwendet werden.

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

Der folgende Code funktioniert NICHT, da er livevon der Selector-Eigenschaft abhängt, die in diesem Fall a.parent()ein ungültiger Selector ist.

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

Unsere addEventMethode wird ausgelöst, aber auch Sie werden den falschen Selektor sehen - a.parent().

Anurag
quelle
Ich denke, das ist das Beste, was wir von jquery bekommen können =). Vielleicht finde ich später die vollständige Lösung. Auf jeden Fall kann das sehr praktisch sein, danke! =)
Fidilip
@ MarkoDumic: Muss veraltet gewesen sein. Der Link ist jetzt tot und der folgende sagt uns nur:No Such jQuery Method Exists
Hippietrail
12
@Levitikon Stimmen Sie eine drei Jahre alte Antwort wirklich ab, weil sie jetzt veraltet ist?! Sie sollten in der Tat die Antwort bearbeiten und eine Warnung
A. Wolff
22

In Zusammenarbeit mit @drzaus haben wir das folgende jQuery-Plugin entwickelt.

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

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

Verwendung und Fallstricke

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

Geige mit QUnit-Tests

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

Wille
quelle
Mir hat gefallen, wohin Sie wollten, also habe ich einige Korrekturen / Änderungen vorgenommen : * Das jQuery-Plugin nutzt das Dienstprogramm jQuery $.map* Optionales Trennzeichen (muss seltsame leere Tag-Namen entfernen) * Müssen Sie nicht hasOwnPropertyin einer foreachSchleife einchecken , um sicher zu sein?
Drzaus
Vielen Dank für die Kommentare. Ich werde dieses Wochenende eine richtige Testsuite einrichten und daran arbeiten, Ihre Vorschläge einzubeziehen.
Will
1
@drzaus Ich habe die Frage aktualisiert. Ich habe beschlossen, das von Ihnen hinzugefügte benutzerdefinierte Trennzeichen wegzulassen, da jedes andere Trennzeichen ' > 'dazu führen würde, dass der Selektor des Elements nicht zurückgegeben wird.
Will
coole, schöne Arbeit; hatte Qunit noch nie gesehen. Ich dachte, das Trennzeichen sei nur zur Präsentation gedacht, aber jetzt verstehe ich, dass es Teil des wörtlichen Auswahlpfads ist.
Drzaus
5

Hast du das versucht?

 $("*").click(function(){
    $(this).attr("id"); 
 });
abhilashv
quelle
3
Versuchen Sie, den *Selektor nicht zu benutzen , er ist sehr langsam!
Ben Carey
3
Dies funktioniert nur, wenn das Element eine ID hat, also nicht so toll.
Glen
2

Ich habe ein jQuery-Plugin veröffentlicht: jQuery Selectorator , Sie können Selector wie folgt erhalten.

$("*").on("click", function(){
  alert($(this).getSelector().join("\n"));
  return false;
});
ngs
quelle
Dies ist der einzige Ansatz, der sich mit geklonten Geschwistern befasst, danke!
Bruno Peres
2

Versuche dies:

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

Fügen Sie einfach eine Ebene über der $ -Funktion hinzu:

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

Jetzt können Sie Dinge wie tun

$ ("a"). Selektor
und gibt auch bei neueren jQuery-Versionen "a" zurück.

Albert Horta
quelle
Das macht genau das, was ich wollte. Es funktioniert verdächtig gut, wenn man bedenkt, wie lange ich danach gesucht habe! Danke Albert.
Mark Notton
1

http://www.selectorgadget.com/ ist ein Lesezeichen, das explizit für diesen Anwendungsfall entwickelt wurde.

Trotzdem stimme ich den meisten anderen Menschen darin zu, dass Sie CSS-Selektoren nur selbst lernen sollten. Der Versuch, sie mit Code zu generieren, ist nicht nachhaltig. :) :)

Paul Irish
quelle
1

Ich habe @ jessegavins Fix einige Korrekturen hinzugefügt.

Dies wird sofort zurückgegeben, wenn das Element eine ID enthält. Ich habe auch eine Namensattributprüfung und einen n-ten untergeordneten Selektor hinzugefügt, falls ein Element keine ID, Klasse oder keinen Namen hat.

Der Name muss möglicherweise überprüft werden, falls mehrere Formulare auf der Seite vorhanden sind und ähnliche Eingaben vorliegen, aber das habe ich noch nicht behandelt.

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
quelle
1

Ich habe sogar nach den oben genannten Lösungen mehrere Elemente erhalten, daher habe ich die Arbeit mit dds1024 erweitert, um ein noch genaueres dom-Element zu erhalten.

zB DIV: n-tes Kind (1) DIV: n-tes Kind (3) DIV: n-tes Kind (1) ARTIKEL: n-tes Kind (1) DIV: n-tes Kind (1) DIV: n-tes Kind (8) DIV : n-tes Kind (2) DIV: n-tes Kind (1) DIV: n-tes Kind (2) DIV: n-tes Kind (1) H4: n-tes Kind (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
quelle
1

Dies kann Ihnen den Auswahlpfad des angeklickten HTML-Elements anzeigen.

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

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

    alert(selectorPath);

    return false;

});
Vivek Kumar
quelle
1

Nun, ich habe dieses einfache jQuery-Plugin geschrieben.

Dies überprüft die ID oder den Klassennamen und versucht, so genau wie möglich zu wählen.

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
quelle
0

Versuchen Sie, den Namen des aktuellen Tags abzurufen, auf das geklickt wurde?

Wenn ja, mach das ..

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

Sie können den "Selektor" nicht wirklich bekommen, der "Selektor" in Ihrem Fall ist *.

Jessegavin
quelle
Ich brauche den Tag-Namen nicht. Ich brauche nur einen Pfad zu dem Element, auf das ich geklickt habe.
Fidilip
1
AH, irgendwohin zu gelangen, ist viel anders als "Selektor". Also brauchen Sie das Element und alle übergeordneten Knotennamen?
Mark Schultheiss
Ich habe eine weitere Antwort veröffentlicht, die Ihrem tatsächlichen Ziel näher kommt. Sie sollten die Frage so bearbeiten, dass sie spezifischer ist.
Jessegavin
0

Javascript-Code für das gleiche, falls jemand es braucht, wie ich es brauchte. Dies ist nur die Übersetzung nur der oben ausgewählten Antwort.

    <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
quelle
0

Unter Berücksichtigung einiger hier gelesener Antworten möchte ich Folgendes vorschlagen:

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

Vielleicht nützlich, um ein jQuery-Plugin zu erstellen?

p1nox
quelle
0

Danke p1nox!

Mein Problem bestand darin, mich wieder auf einen Ajax-Aufruf zu konzentrieren, der einen Teil des Formulars veränderte.

$.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();
                }
});

Ich musste nur Ihre Funktion in ein jQuery-Plugin kapseln:

    !(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
quelle
-3

Wie wäre es mit:

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

Ich glaube nicht, dass jQuery den verwendeten Auswahltext speichert. Wie würde das funktionieren, wenn Sie so etwas tun würden:

$("div").find("a").click(function() {
    // what would expect the 'selector' to be here?
});
Dean Harding
quelle
jQuery erstellt intern den Selektor $('div').find('a').selectoris div a. Wenn die Ereignisse nicht über die jQuery-Funktionen, sondern über einen Wrapper erstellt werden, kann der Selektor meines Erachtens als Datenargumente an den Ereignishandler übergeben werden.
Anurag
1
Ist das eigentlich eine ernsthafte Antwort?
Glen
-5

Die beste Antwort wäre

var selector = '#something';

$(selector).anything(function(){
  console.log(selector);
});
Anny
quelle
4
Dies scheint überhaupt nicht die beste Antwort zu sein.
Alex