Bagaimana saya bisa mendapatkan selector dari objek jQuery

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

Apakah ada cara mudah untuk mendapatkan selektor$(this) ? Ada cara untuk memilih elemen dengan selektornya, tapi bagaimana dengan mendapatkan selektor dari elemen ?

Fidilip
sumber
Penasaran kenapa ini bisa berguna? Apa yang Anda katakan di sini (secara semantik) adalah untuk setiap elemen yang direferensikan sebagai $ (this) ... elemen itu sendiri adalah $ (this) sehingga selektor tidak diperlukan. Anda punya objek ...
BenAlabaster
1
Anda SANGAT menyadari bahwa klik dengan elemen bersarang akan menghasilkan lebih dari satu? div dalam tubuh, dll. atau apakah saya terlalu lelah pada saat ini?
Mark Schultheiss
2
Akan sangat membantu jika Anda dapat menggambarkan 'tujuan akhir' dari apa yang ingin Anda capai. Anda mungkin mendapat bantuan yang lebih baik dengan cara itu.
jessegavin
3
Sebuah elemen dapat dipilih dengan berbagai cara berbeda. Juga, selektor! == jalur. Apa yang Anda harapkan untuk dilakukan dengan informasi ini?
menipu
2
Ini bisa berguna jika Anda sudah menemukan elemen JQuery, dan menggunakan plugin / module / subrutin, yang memerlukan selektor untuk bekerja (mungkin di luar kendali Anda).
Andy

Jawaban:

57

Oke, jadi dalam komentar di atas penanya pertanyaan Fidilipmengatakan bahwa yang sebenarnya dia cari adalah mendapatkan jalur ke elemen saat ini.

Berikut ini skrip yang akan "memanjat" pohon leluhur DOM dan kemudian membangun pemilih yang cukup spesifik termasuk atribut idatau apa pun classpada item yang diklik.

Lihat ini bekerja di 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>

Misalnya, jika Anda mengklik daftar item daftar bersarang ke-2 dalam HTML di bawah, Anda akan mendapatkan hasil sebagai berikut:

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

jessegavin
sumber
2
Terima kasih! Saya akan menggunakan kode Anda dengan satu modifikasi saat bergabung ... join(" > ");, akan memberi saya anak langsung dan karenanya jalur yang lebih ketat .
nonsensickle
FANTASTIS ... saya akan menggunakannya untuk ekstensi chrome saya. Hanya satu hal, terkadang id digunakan dengan titik dua ':' diawali, yang dapat kita ganti dengan '\\:'
Savaratkar
Panggilan bagus @nonsensickle. Saya memperbarui contoh saya, dan menghapus pernyataan if juga.
jessegavin
Fragmen kode di atas tidak mengembalikan kelas untuk objek SVG. Berikut adalah jsFiddle yang berfungsi untuk SVG: http://jsfiddle.net/mikemsq/vbykja4x/7/ .
mikemsq
32

::PERINGATAN::
.selector sudah tidak digunakan lagi mulai versi 1.7, dihapus sejak 1.9

Objek jQuery memiliki properti pemilih yang saya lihat saat menggali kodenya kemarin. Tidak tahu apakah itu didefinisikan dalam dokumen seberapa andal itu (untuk pemeriksaan di masa mendatang). Tapi itu berhasil!

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

Edit : Jika Anda menemukan pemilih di dalam acara, informasi tersebut idealnya harus menjadi bagian dari acara itu sendiri dan bukan elemen karena sebuah elemen dapat memiliki beberapa peristiwa klik yang ditetapkan melalui berbagai pemilih. Solusinya adalah dengan menggunakan pembungkus ke sekitar bind(), click()dll. Untuk menambahkan acara daripada menambahkannya secara langsung.

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

Selektor sedang diteruskan sebagai properti objek bernama selector. Akses sebagaievent.data.selector .

Mari kita coba di beberapa 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
});

Penafian : Ingatlah bahwa seperti halnya live()kejadian, properti selektor mungkin tidak valid jika metode traversal DOM digunakan.

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

Kode di bawah TIDAK akan berfungsi, karena livebergantung pada properti selector yang dalam hal ini adalah a.parent()- selector yang tidak valid.

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

addEventMetode kami akan aktif, tetapi Anda juga akan melihat pemilih yang salah - a.parent().

Anurag
sumber
Saya pikir ini adalah yang terbaik yang kami dapatkan dari jquery =). Mungkin saya akan menemukan solusi lengkapnya nanti. Bagaimanapun ini bisa sangat berguna, terima kasih! =)
Fidilip
@MarkoDumic: Pasti sudah usang. Tautan sekarang sudah mati dan mengikutinya hanya memberi tahu kita:No Such jQuery Method Exists
hippietrail
12
@Levitikon Apakah Anda benar-benar downvoting jawaban tiga tahun karena sekarang sudah usang ?! Anda memang harus mengedit jawaban dan memberi peringatan
A. Wolff
22

Bekerja sama dengan @drzaus, kami telah membuat plugin jQuery berikut.

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

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

Penggunaan dan 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 test

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

Akan
sumber
Saya suka ke mana Anda pergi, jadi saya membuat beberapa perbaikan / perubahan : * plugin jQuery memanfaatkan utilitas jQuery $.map* pembatas opsional (perlu menghapus tagNames kosong yang aneh) * tidakkah Anda perlu memeriksa hasOwnPropertydalam satu foreachlingkaran agar aman?
drzaus
Terima kasih atas komentarnya, saya akan menyiapkan rangkaian pengujian yang tepat akhir pekan ini dan bekerja untuk menggabungkan saran Anda.
Akankah
1
@drzaus Saya telah memperbarui pertanyaannya. Saya memutuskan untuk meninggalkan pembatas khusus yang Anda tambahkan karena pembatas apa pun selain ' > 'akan menyebabkannya tidak mengembalikan pemilih elemen.
Akankah
keren, kerja bagus; belum pernah melihat qunit sebelumnya. Saya pikir pembatas itu hanya untuk presentasi, tetapi sekarang saya mengerti bahwa itu adalah bagian dari jalur pemilih literal.
drzaus
5

Apakah kamu sudah mencobanya?

 $("*").click(function(){
    $(this).attr("id"); 
 });
abhilashv.dll
sumber
3
Cobalah untuk tidak menggunakan *selektor, ini sangat lambat!
Ben Carey
3
Ini hanya berfungsi jika elemen memiliki ID jadi tidak terlalu bagus.
Glen
2

Saya telah merilis plugin jQuery: jQuery Selectorator , Anda bisa mendapatkan selector seperti ini.

$("*").on("click", function(){
  alert($(this).getSelector().join("\n"));
  return false;
});
ngs
sumber
Ini adalah satu-satunya pendekatan yang berhubungan dengan saudara kandung kloning, terima kasih!
Bruno Peres
2

Coba ini:

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

Cukup tambahkan lapisan di atas $ function dengan cara ini:

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

Sekarang Anda dapat melakukan hal-hal seperti

$ ("a"). selector
dan akan mengembalikan "a" bahkan pada versi jQuery yang lebih baru.

Albert Horta
sumber
Ini melakukan apa yang saya inginkan. Ini bekerja dengan mencurigakan dengan baik mengingat sudah berapa lama saya mencari ini! Terima kasih Albert.
Mark Notton
1

http://www.selectorgadget.com/ adalah bookmarklet yang dirancang secara eksplisit untuk kasus penggunaan ini.

Yang mengatakan, saya setuju dengan kebanyakan orang lain bahwa Anda hanya harus mempelajari pemilih CSS sendiri, mencoba membuatnya dengan kode tidak berkelanjutan. :)

Paul Irish
sumber
1

Saya menambahkan beberapa perbaikan untuk perbaikan @ jessegavin.

Ini akan langsung kembali jika ada ID pada elemen. Saya juga menambahkan pemeriksaan atribut nama dan pemilih anak ke-n jika elemen tidak memiliki id, kelas, atau nama.

Namanya mungkin perlu dilingkupi jika ada beberapa formulir di halaman dan memiliki masukan yang serupa, tetapi saya belum menanganinya.

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

Saya mendapatkan beberapa elemen bahkan setelah solusi di atas, jadi saya memperpanjang pekerjaan dds1024, untuk elemen dom yang lebih mengarah ke pin.

misal DIV: anak ke-n (1) DIV: anak ke-n (3) DIV: anak ke-n (1) ARTICLE: anak ke-n (1) DIV: anak ke-n (1) DIV: anak ke-n (8) DIV : anak ke-n (2) DIV: anak ke-n (1) DIV: anak ke-n (2) DIV: anak ke-n (1) H4: anak ke-n (2)

Kode:

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

Ini bisa memberi Anda jalur pemilih dari elemen HTML yang diklik-

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

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

    alert(selectorPath);

    return false;

});
Vivek Kumar
sumber
1

Nah, saya menulis plugin jQuery sederhana ini.

Ini memeriksa id atau nama kelas, dan mencoba memberikan pemilih yang tepat sebanyak mungkin.

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

Apakah Anda mencoba mendapatkan nama tag saat ini yang diklik?

Jika ya, lakukan ini ..

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

Anda tidak bisa benar-benar mendapatkan "selector", "selector" dalam kasus Anda adalah *.

jessegavin
sumber
Saya tidak membutuhkan nama tag. Saya hanya perlu jalur ke elemen yang saya klik.
Fidilip
1
AH, mulai mendapatkan suatu tempat "jalur ke elemen" jauh berbeda dari "pemilih". JADI Anda membutuhkan elemen, dan semua nama simpul orang tuanya?
Mark Schultheiss
Saya telah memposting jawaban lain yang lebih mengarah ke tujuan Anda yang sebenarnya. Anda harus mengedit pertanyaan agar lebih spesifik.
jessegavin
0

Kode Javascript untuk hal yang sama, jika ada yang membutuhkan, karena saya membutuhkannya. Ini hanya terjemahan dari jawaban yang dipilih di atas.

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

Mempertimbangkan beberapa jawaban yang dibaca di sini saya ingin mengusulkan ini:

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

Mungkin berguna untuk membuat plugin jQuery?

p1nox
sumber
0

Terima kasih p1nox!

Masalah saya adalah mengembalikan fokus pada panggilan ajax yang mengubah bagian dari formulir.

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

Saya hanya perlu merangkum fungsi Anda dalam 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);
Patrick
sumber
-3

Bagaimana tentang:

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

Saya tidak percaya jQuery menyimpan teks pemilih yang digunakan. Lagi pula, bagaimana itu akan berhasil jika Anda melakukan sesuatu seperti ini:

$("div").find("a").click(function() {
    // what would expect the 'selector' to be here?
});
Dean Harding
sumber
jQuery secara internal membangun selektor $('div').find('a').selectortersebut div a. Jika peristiwa tidak dibuat melalui fungsi jQuery, tetapi sebagai pembungkus, saya yakin pemilih dapat diteruskan sebagai argumen data ke pengendali peristiwa.
Anurag
1
Apakah ini jawaban yang serius?
Glen
-5

Jawaban terbaiknya adalah

var selector = '#something';

$(selector).anything(function(){
  console.log(selector);
});
Anny
sumber
4
Ini sepertinya bukan jawaban terbaik sama sekali.
Alex