Dapatkan elemen berdasarkan atribut saat querySelectorAll tidak tersedia tanpa menggunakan perpustakaan?

123
<p data-foo="bar">

Bagaimana Anda bisa melakukan hal yang sama dengan

document.querySelectorAll('[data-foo]')

di mana querySelectorAll yang tidak tersedia ?

Saya membutuhkan solusi asli yang berfungsi setidaknya di IE7. Saya tidak peduli tentang IE6.

ryanve
sumber
lihat pustaka pemilih javascript sizzle.js
epoch
1
Bagus ya, satu-satunya pemilihan yang perlu saya lakukan adalah atribut data jadi saya mencoba mencari cara paling sederhana untuk menambalnya tanpa menarik seluruh mesin pemilih seperti Sizzle. Tapi bagus untuk melihat sumbernya. BTW mesin pemilih hebat lainnya adalah github.com/ded/qwery
ryanve
@ryanve, terima kasih saya akan melihatnya :)
epoch
Solusi kerja yang saya gunakan ada di github.com/ryanve/dope/blob/master/dope.js dalam metode yang disebut 'queryAttr'
ryanve
7
Lol, pertanyaan Anda adalah jawaban saya. Jadi ini datang dengan pertanyaan lain. Dalam situasi apa yang querySelectorAlltidak tersedia? note - I don't care all IE
vzhen

Jawaban:

136

Anda bisa menulis fungsi yang menjalankan getElementsByTagName ('*'), dan hanya mengembalikan elemen tersebut dengan atribut "data-foo":

function getAllElementsWithAttribute(attribute)
{
  var matchingElements = [];
  var allElements = document.getElementsByTagName('*');
  for (var i = 0, n = allElements.length; i < n; i++)
  {
    if (allElements[i].getAttribute(attribute) !== null)
    {
      // Element exists with attribute. Add to array.
      matchingElements.push(allElements[i]);
    }
  }
  return matchingElements;
}

Kemudian,

getAllElementsWithAttribute('data-foo');
kevinfahy.dll
sumber
8
Menggunakan != nulladalah cara yang ideal (lebih baik daripada komentar saya di atas) karena di IE tua adalah mungkin untuk getAttribute untuk mengembalikan nilai yang typeofadalah'number'
ryanve
1
Mengapa menggunakan, document.getElementsByTagName('*')bukan document.all?
pedrozath
1
Mengapa tidak menggunakan hasAttributedaripada getAttribute() !== null, karena Anda hanya ingin memeriksa keberadaan dan bukan nilainya?
rvighne
61

Menggunakan

//find first element with "someAttr" attribute
document.querySelector('[someAttr]')

atau

//find all elements with "someAttr" attribute
document.querySelectorAll('[someAttr]') 

untuk menemukan elemen berdasarkan atribut. Sekarang didukung di semua browser yang relevan (bahkan IE8): http://caniuse.com/#search=queryselector

Pylinux
sumber
2
Bagaimana ini memiliki begitu banyak suara positif ketika pertanyaan secara eksplisit meminta: "Saya memerlukan solusi asli yang berfungsi setidaknya di IE7 ". Kedua, tautan tersebut menyatakan bahwa dukungan dimulai di IE11 meskipun sebenarnya dimulai dari IE8 - mungkin ini harus ditukar ke developer.mozilla.org/en-US/docs/Web/API/Element/… sehingga benar-benar mendukung jawabannya. ..?
Zze
7
Alasan untuk semua upvote, dan alasan saya membuat jawabannya, adalah bahwa pertanyaan SO ini benar - benar tua, jadi ketika Anda mencari cara menemukan elemen DOM, Anda menemukan pertanyaan ini sangat tinggi dalam hasil pencarian, dan karena itulah orang sedang mencari upvote mereka. Kegunaan> akurasi historis. Kedua, tautannya masih berfungsi dengan baik, hanya saja caniuse.com menyembunyikan browser lama, jika Anda beralih ke "Penggunaan relatif", Anda masih akan melihat browser lama.
Pylinux
Bekerja dengan sempurna. Cepat dan sederhana
Dawson B
Ini tahun 2020. Ini harus menjadi jawaban yang diterima sekarang.
NearHuscarl
44

Saya bermain-main sedikit dan berakhir dengan solusi kasar ini:

function getElementsByAttribute(attribute, context) {
  var nodeList = (context || document).getElementsByTagName('*');
  var nodeArray = [];
  var iterator = 0;
  var node = null;

  while (node = nodeList[iterator++]) {
    if (node.hasAttribute(attribute)) nodeArray.push(node);
  }

  return nodeArray;
}

Penggunaannya cukup sederhana, dan berfungsi bahkan di IE8:

getElementsByAttribute('data-foo');
// or with parentNode
getElementsByAttribute('data-foo', document);

http://fiddle.jshell.net/9xaxf6jr/

Tetapi saya merekomendasikan untuk menggunakan querySelector/ Alluntuk ini (dan untuk mendukung browser lama gunakan polyfill ):

document.querySelectorAll('[data-foo]');
yckart
sumber
Ya, +1 untuk querySelectorAll. Sebuah tes jsperf cepat jsperf.com/custom-vs-selectorall-attributes menunjukkan bahwa itu jauh lebih cepat daripada jawaban yang diterima ... sayangnya itu tidak IE 7 kompatibel :(
Sebastien Daniel
11

Coba ini berhasil

document.querySelector ('[atribut = "nilai"]')

contoh:

document.querySelector('[role="button"]')
BrainabilGH
sumber
5

Itu juga berfungsi:

document.querySelector([attribute="value"]);

Begitu:

document.querySelector([data-foo="bar"]);
CallMarl
sumber
2
Ini kehilangan tanda kutip tunggal di querySelector sebenarnya. Seharusnya: document.querySelector('[data-foo="bar"]');
Brettins
1

Coba ini - Saya sedikit mengubah jawaban di atas:

var getAttributes = function(attribute) {
    var allElements = document.getElementsByTagName('*'),
        allElementsLen = allElements.length,
        curElement,
        i,
        results = [];

    for(i = 0; i < allElementsLen; i += 1) {
        curElement = allElements[i];

        if(curElement.getAttribute(attribute)) {
            results.push(curElement);
        }
    }

    return results;
};

Kemudian,

getAttributes('data-foo');
Menyerah Lohia
sumber
3
Apa yang Anda ubah dan mengapa?
Artjom B.
1

Sedikit modifikasi pada jawaban @kevinfahy , untuk memungkinkan mendapatkan atribut dengan nilai jika diperlukan:

function getElementsByAttributeValue(attribute, value){
  var matchingElements = [];
  var allElements = document.getElementsByTagName('*');
  for (var i = 0, n = allElements.length; i < n; i++) {
    if (allElements[i].getAttribute(attribute) !== null) {
      if (!value || allElements[i].getAttribute(attribute) == value)
        matchingElements.push(allElements[i]);
    }
  }
  return matchingElements;
}
Z. Khullah
sumber
0

Jangan gunakan di Browser

Di browser, gunakan document.querySelect('[attribute-name]').

Tetapi jika Anda menguji unit dan dom palsu Anda memiliki implementasi querySelector yang tidak stabil, ini akan berhasil.

Ini adalah jawaban @ kevinfahy, baru saja dipangkas menjadi sedikit dengan fungsi panah lemak ES6 dan dengan mengubah HtmlCollection menjadi array dengan biaya keterbacaan mungkin.

Jadi ini hanya akan bekerja dengan transpiler ES6. Juga, saya tidak yakin bagaimana performanya dengan banyak elemen.

function getElementsWithAttribute(attribute) {
  return [].slice.call(document.getElementsByTagName('*'))
    .filter(elem => elem.getAttribute(attribute) !== null);
}

Dan inilah varian yang akan mendapatkan atribut dengan nilai tertentu

function getElementsWithAttributeValue(attribute, value) {
  return [].slice.call(document.getElementsByTagName('*'))
    .filter(elem => elem.getAttribute(attribute) === value);
}
raksasa
sumber