Come posso ottenere il selettore dall'oggetto jQuery


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

C'è un modo semplice per ottenere il selettore da$(this) ? C'è un modo per selezionare un elemento dal suo selettore, ma per quanto riguarda ottenere il selettore dall'elemento ?


Sei solo curioso del motivo per cui sarebbe utile? Quello che stai dicendo qui (semanticamente) è per ogni elemento referenziato come $ (questo) ... l'elemento stesso è $ (questo) quindi il selettore non è richiesto. Hai l'oggetto ...
BenAlabaster

1
ti rendi conto che il clic con elementi annidati restituirà più di uno? div in un corpo, ecc. o sono troppo stanco in questo frangente?
Mark Schultheiss

2
Sarebbe utile se potessi descrivere l '"obiettivo finale" di ciò che stai cercando di realizzare. Potresti ottenere un aiuto migliore in questo modo.
jessegavin

3
Un elemento può essere selezionato in una miriade di modi diversi. Inoltre, selector! == path. Cosa ti aspetti di fare con queste informazioni?
inganno

2
Questo può essere utile se hai già trovato un elemento JQuery e stai usando un plugin / modulo / subroutine, che richiede un selettore per funzionare (possibilmente fuori dal tuo controllo).
Andy

Risposte:


57

Ok, quindi in un commento sopra la domanda che pone Fidilip detto che ciò che sta davvero cercando è ottenere il percorso per l'elemento corrente.

Ecco uno script che "scalerà" l'albero degli antenati DOM e quindi creerà un selettore abbastanza specifico che includa qualsiasi idoclass attributi sull'elemento cliccato.

Guardalo funzionare su 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>

Ad esempio, se si facesse clic sulla seconda voce di elenco nidificata dell'elenco nell'HTML di seguito, si otterrebbe il seguente risultato:

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


2
Grazie! Userò il tuo codice con una modifica sul join ... join(" > ");, mi fornirà i figli immediati e quindi un percorso più rigoroso .
nonsensickle

FANTASTICO ... lo userò per la mia estensione chrome. Solo una cosa, a volte id viene utilizzato con i due punti ':' prefisso, che possiamo sostituire con '\\:'
Savaratkar

Buona chiamata @nonsensickle. Ho aggiornato il mio esempio e rimosso anche un'istruzione if.
jessegavin

Il frammento di codice sopra non restituisce classi per oggetti SVG. Ecco un jsFiddle che funziona per SVG: http://jsfiddle.net/mikemsq/vbykja4x/7/ .
mikemsq

32

:: WARNING ::
.selector è stato deprecato dalla versione 1.7, rimossa dalla 1.9

L'oggetto jQuery ha una proprietà selector che ho visto ieri durante lo scavo nel suo codice. Non so se è definito nei documenti quanto sia affidabile (per prove future). Ma funziona!

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

Modifica : se dovessi trovare il selettore all'interno dell'evento, tali informazioni dovrebbero idealmente far parte dell'evento stesso e non dell'elemento perché un elemento potrebbe avere più eventi di clic assegnati tramite vari selettori. Una soluzione potrebbe essere quella di utilizzare un wrapper per around bind(), click()ecc. Per aggiungere eventi invece di aggiungerlo direttamente.

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

Il selettore viene passato come proprietà di un oggetto denominata selector. Accedi comeevent.data.selector .

Proviamolo su qualche 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
});

Dichiarazione di non responsabilità : ricorda che, proprio come per gli live()eventi, la proprietà selector potrebbe non essere valida se vengono utilizzati metodi di attraversamento DOM.

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

Il codice seguente NON funzionerà, poiché livesi basa sulla proprietà selector che in questo caso è a.parent()- un selettore non valido.

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

Il nostro addEventmetodo verrà attivato, ma anche tu vedrai il selettore sbagliato - a.parent().


Penso che questo sia il meglio che possiamo ottenere da jquery =). Forse troverò la soluzione completa più tardi. Comunque questo può essere davvero utile, grazie! =)
Fidilip

@MarkoDumic: deve essere stato deprecato. Il collegamento ora è morto e in seguito ci dice solo:No Such jQuery Method Exists
hippietrail

12
@ Levitikon Stai davvero votando una risposta vecchia di tre anni perché ora è deprecata ?! Dovresti infatti modificare la risposta e mettere un avviso
A. Wolff

22

In collaborazione con @drzaus abbiamo creato il seguente plugin jQuery.

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

Javascript minimizzato

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

Utilizzo e trucchi

<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 con test QUnit

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


Mi è piaciuto dove stavi andando, quindi ho apportato alcune correzioni / modifiche : * il plugin jQuery sfrutta l'utilità jQuery $.map* delimitatore opzionale (deve rimuovere strani tagNames vuoti) * non è necessario controllare hasOwnPropertyin un foreachciclo per essere al sicuro?
drzaus

Grazie per i commenti, questo fine settimana creerò una suite di test adeguata e lavorerò per incorporare i tuoi suggerimenti.
Sarà il

1
@drzaus ho aggiornato la domanda. Ho deciso di tralasciare il delimitatore personalizzato che hai aggiunto poiché qualsiasi delimitatore diverso da ' > 'non restituirebbe il selettore dell'elemento.
Il

bello, bel lavoro; non aveva mai visto qunit prima. Ho pensato che il delimitatore fosse solo per la presentazione, ma ora capisco che fa parte del percorso del selettore letterale.
drzaus

5

Hai provato questo?

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

3
Cerca di non usare il *selettore, è molto lento!
Ben Carey

3
Funziona solo se l'elemento ha un ID quindi non eccezionale.
Glen

2

Ho rilasciato un plugin jQuery: jQuery Selectorator , puoi ottenere un selettore come questo.

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

Questo è l'unico approccio che si occupa di fratelli clonati, grazie!
Bruno Peres

2

Prova questo:

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

2

Basta aggiungere un livello sopra la funzione $ in questo modo:

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

Ora puoi fare cose come

$ ( "A"). Selettore
e restituirà "a" anche sulle versioni più recenti di jQuery.


Questo fa esattamente quello che volevo. Funziona sospettosamente bene visto quanto tempo l'ho cercato! Grazie Albert.
Mark Notton

1

http://www.selectorgadget.com/ è un bookmarklet progettato esplicitamente per questo caso d'uso.

Detto questo, sono d'accordo con la maggior parte delle altre persone sul fatto che dovresti imparare da solo i selettori CSS, provare a generarli con il codice non è sostenibile. :)


1

Ho aggiunto alcune correzioni alla correzione di @ jessegavin.

Questo tornerà immediatamente se c'è un ID sull'elemento. Ho anche aggiunto un controllo dell'attributo del nome e un selettore n-esimo figlio nel caso in cui un elemento non abbia ID, classe o nome.

Il nome potrebbe richiedere l'ambito nel caso in cui ci siano più moduli sulla pagina e hanno input simili, ma non l'ho ancora gestito.

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

1

Stavo ottenendo più elementi anche dopo le soluzioni di cui sopra, quindi ho esteso il lavoro a dds1024, per un elemento dom ancora più preciso.

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

Codice:

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

1

Questo può farti ottenere il percorso del selettore dell'elemento HTML cliccato-

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

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

    alert(selectorPath);

    return false;

});

1

Bene, ho scritto questo semplice plugin jQuery.

Questo controlla l'ID o il nome della classe e cerca di fornire il più esatto selettore possibile.

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

0

Stai cercando di ottenere il nome del tag corrente su cui è stato fatto clic?

Se è così, fallo ..

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

Non puoi davvero ottenere il "selettore", il "selettore" nel tuo caso lo è *.


Non ho bisogno del nome del tag. Ho bisogno solo del percorso dell'elemento su cui ho fatto clic.
Fidilip

1
AH, iniziare a ottenere da qualche parte "path to the element" è molto diverso da "selector". Quindi hai bisogno dell'elemento e di tutti i suoi nomi di nodo padre?
Mark Schultheiss

Ho pubblicato un'altra risposta che si avvicina maggiormente al tuo obiettivo effettivo. È necessario modificare la domanda in modo che sia più specifica.
jessegavin

0

Codice Javascript per lo stesso, nel caso qualcuno ne abbia bisogno, come ne avevo bisogno. Questa è solo la traduzione della risposta selezionata sopra.

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

0

Tenendo conto di alcune risposte lette qui vorrei proporre questo:

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

Forse utile per creare un plugin jQuery?


0

Grazie p1nox!

Il mio problema era riportare l'attenzione su una chiamata ajax che stava modificando parte del modulo.

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

Avevo solo bisogno di incapsulare la tua funzione in un plugin jQuery:

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


-3

Che ne dite di:

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

Non credo che jQuery memorizzi il testo del selettore che è stato utilizzato. Dopotutto, come funzionerebbe se facessi qualcosa del genere:

$("div").find("a").click(function() {
    // what would expect the 'selector' to be here?
});

jQuery costruisce internamente il selettore $('div').find('a').selectoris div a. Se gli eventi non vengono creati tramite le funzioni jQuery, ma invece un wrapper, credo che il selettore potrebbe essere passato come argomenti di dati al gestore di eventi.
Anurag

1
Questa è davvero una risposta seria?
Glen

-5

La migliore risposta sarebbe

var selector = '#something';

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

4
Questa non sembra affatto la risposta migliore.
Alex
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.