¿Cómo puedo obtener el selector del objeto jQuery?

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

¿Existe una forma fácil de obtener el selector$(this) ? Hay una forma de seleccionar un elemento por su selector, pero ¿qué hay de obtener el selector del elemento ?

Fidilip
fuente
¿Solo tienes curiosidad por saber por qué esto sería útil? Lo que está diciendo aquí (semánticamente) es para cada elemento referenciado como $ (this) ... el elemento en sí es $ (this), por lo que no se requiere el selector. Tienes el objeto ...
BenAlabaster
1
¿Se da cuenta de que el clic con elementos anidados devolverá más de uno? div en un cuerpo, etc. o estoy demasiado cansado en este momento?
Mark Schultheiss
2
Sería útil si pudiera describir el 'objetivo final' de lo que está tratando de lograr. De esa manera, podría obtener mejor ayuda.
jessegavin
3
Un elemento se puede seleccionar de muchas formas diferentes. Además, selector! == ruta. ¿Qué espera hacer con esta información?
diciembre
2
Esto puede ser útil si ya encontró un elemento de JQuery y está utilizando un complemento / módulo / subrutina, que requiere un selector para funcionar (posiblemente fuera de su control).
Andy

Respuestas:

57

De acuerdo, en un comentario anterior, el autor de la pregunta Fidilipdijo que lo que realmente busca es obtener la ruta al elemento actual.

Aquí hay un script que va a "subir" el árbol DOM antepasado y luego construir selector bastante específico incluyendo cualquier ido classatributos en el elemento ha hecho clic.

Véalo funcionando en 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>

Por ejemplo, si hiciera clic en el segundo elemento de la lista anidada de la lista en el HTML a continuación, obtendría el siguiente resultado:

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

jessegavin
fuente
2
¡Gracias! Usaré su código con una modificación en la combinación ... join(" > ");, me dará los hijos inmediatos y, por lo tanto, una ruta más estricta .
sin sentido
FANTÁSTICO ... lo voy a usar para mi extensión de Chrome. Solo una cosa, en ocasiones id se usa con dos puntos ':' prefijado, que podemos reemplazar con '\\:'
Savaratkar
Buena llamada @nonsensickle. Actualicé mi ejemplo y también eliminé una declaración if.
jessegavin
El fragmento de código anterior no devuelve clases para objetos SVG. Aquí hay un jsFiddle que funciona para SVG: http://jsfiddle.net/mikemsq/vbykja4x/7/ .
mikemsq
32

::ADVERTENCIA::
.selector ha quedado obsoleto a partir de la versión 1.7, eliminado a partir de 1.9

El objeto jQuery tiene una propiedad de selector que vi cuando indagué en su código ayer. No sé si está definido en los documentos, es qué tan confiable es (para pruebas futuras). ¡Pero funciona!

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

Editar : si encontrara el selector dentro del evento, esa información idealmente debería ser parte del evento en sí y no el elemento porque un elemento podría tener múltiples eventos de clic asignados a través de varios selectores. Una solución sería usar un contenedor para alrededor bind(), click()etc. para agregar eventos en lugar de agregarlos directamente.

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

El selector se pasa como propiedad de un objeto con nombre selector. Acceda a él como event.data.selector.

Probémoslo con algunas marcas ( 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
});

Descargo de responsabilidad : recuerde que, al igual que con los live()eventos, la propiedad del selector puede no ser válida si se utilizan métodos de recorrido DOM.

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

El siguiente código NO funcionará, ya que se livebasa en la propiedad del selector, que en este caso es a.parent()un selector no válido.

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

Nuestro addEventmétodo se activará, pero usted también verá el selector incorrecto - a.parent().

Anurag
fuente
Creo que esto es lo mejor que obtenemos de jquery =). Quizás encuentre una solución completa más tarde. De todos modos, esto puede ser muy útil, ¡gracias! =)
Fidilip
@MarkoDumic: Debe haber quedado obsoleto. El enlace ahora está muerto y No Such jQuery Method Exists
seguirlo
12
@Levitikon ¿Realmente estás rechazando una respuesta de hace tres años porque ahora está obsoleta? De hecho, debería editar la respuesta y poner una advertencia
A. Wolff
22

En colaboración con @drzaus, hemos creado el siguiente complemento 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 reducido

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

Uso y errores

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

Será
fuente
Me gustó el lugar al que ibas, así que hice algunas correcciones / cambios : * El complemento jQuery aprovecha la utilidad jQuery $.map* delimitador opcional (necesita eliminar los nombres de etiquetas vacíos extraños) * ¿no necesitas verificar hasOwnPropertyun foreachbucle para estar seguro?
drzaus
Gracias por los comentarios, configuraré un conjunto de pruebas adecuado en un violín este fin de semana y trabajaré para incorporar sus sugerencias.
Will el
1
@drzaus He actualizado la pregunta. Decidí omitir el delimitador personalizado que agregó, ya que cualquier delimitador que ' > 'no sea haría que no devolviera el selector del elemento.
Will el
genial, buen trabajo; no había visto qunit antes. Pensé que el delimitador era solo para la presentación, pero ahora entiendo que es parte de la ruta del selector literal.
drzaus
5

¿Intentaste esto?

 $("*").click(function(){
    $(this).attr("id"); 
 });
abhilashv
fuente
3
Intenta no usar el *selector, ¡es muy lento!
Ben Carey
3
Esto solo funciona si el elemento tiene un ID, por lo que no es tan bueno.
Glen
2

Lancé un complemento de jQuery: jQuery Selectorator , puedes obtener un selector como este.

$("*").on("click", function(){
  alert($(this).getSelector().join("\n"));
  return false;
});
ngs
fuente
Este es el único enfoque que se ocupa de los hermanos clonados, ¡gracias!
Bruno Peres
2

Prueba esto:

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

Simplemente agregue una capa sobre la función $ de esta manera:

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

Ahora puedes hacer cosas como

$ ("a"). selector
y devolverá "a" incluso en las versiones más recientes de jQuery.

Albert Horta
fuente
Esto hace exactamente lo que quería. ¡Funciona sospechosamente bien dado cuánto tiempo he buscado esto! Gracias Albert.
Mark Notton
1

http://www.selectorgadget.com/ es un bookmarklet diseñado explícitamente para este caso de uso.

Dicho esto, estoy de acuerdo con la mayoría de las personas en que debería aprender los selectores de CSS usted mismo, intentar generarlos con código no es sostenible. :)

Paul irlandés
fuente
1

Agregué algunas correcciones a la corrección de @ jessegavin.

Esto volverá de inmediato si hay una ID en el elemento. También agregué una verificación de atributo de nombre y un selector de n-ésimo niño en caso de que un elemento no tenga identificación, clase o nombre.

Es posible que el nombre necesite un alcance en caso de que haya varios formularios en la página y tengan entradas similares, pero aún no lo manejé.

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

Obtuve múltiples elementos incluso después de las soluciones anteriores, así que extendí el trabajo de dds1024, para aún más elementos dom que señalan.

p. ej. DIV: nth-child (1) DIV: nth-child (3) DIV: nth-child (1) ARTÍCULO: 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)

Código:

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

Esto puede obtener la ruta del selector del elemento HTML en el que se hizo clic.

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

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

    alert(selectorPath);

    return false;

});
Vivek Kumar
fuente
1

Bueno, escribí este sencillo complemento de jQuery.

Esto verifica la identificación o el nombre de la clase, e intenta dar el selector más exacto posible.

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

¿Está intentando obtener el nombre de la etiqueta actual en la que se hizo clic?

Si es así, haz esto ...

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

Realmente no puede obtener el "selector", el "selector" en su caso es *.

jessegavin
fuente
No necesito el nombre de la etiqueta. Solo necesito la ruta al elemento en el que hice clic.
Fidilip
1
AH, comenzar a llegar a algún lugar "ruta al elemento" es muy diferente a "selector". Entonces, ¿necesita el elemento y todos sus nombres de nodo padres?
Mark Schultheiss
He publicado otra respuesta que se acerca más a su objetivo real. Debes editar la pregunta para que sea más específica.
jessegavin
0

Código Javascript para el mismo, en caso de que alguien lo necesite, como yo lo necesitaba. Esta es solo la traducción solo de la respuesta seleccionada anteriormente.

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

Teniendo en cuenta algunas respuestas leídas aquí, me gustaría proponer esto:

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

¿Quizás sea útil para crear un complemento jQuery?

p1nox
fuente
0

¡Gracias p1nox!

Mi problema era volver a centrarme en una llamada ajax que estaba modificando parte del formulario.

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

Solo necesitaba encapsular su función en un complemento 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);
Patricio
fuente
-3

Qué tal si:

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

No creo que jQuery almacene el texto del selector que se usó. Después de todo, ¿cómo funcionaría eso si hicieras algo como esto?

$("div").find("a").click(function() {
    // what would expect the 'selector' to be here?
});
Dean Harding
fuente
jQuery construye internamente el selector $('div').find('a').selectores div a. Si los eventos no se crean a través de las funciones de jQuery, sino un contenedor, creo que el selector podría pasarse como argumentos de datos al controlador de eventos.
Anurag
1
¿Es esta realmente una respuesta seria?
Glen
-5

La mejor respuesta seria

var selector = '#something';

$(selector).anything(function(){
  console.log(selector);
});
Anny
fuente
4
Esta no parece la mejor respuesta en absoluto.
Alex