javascript document.getElementsByClassName tương thích với IE


76

Phương pháp tốt nhất để truy xuất một mảng các phần tử có một lớp nhất định là gì?

Tôi sẽ sử dụng document.getElementsByClassName nhưng IE không hỗ trợ nó.

Vì vậy, tôi đã thử giải pháp của Jonathan Snook :

function getElementsByClassName(node, classname) {
    var a = [];
    var re = new RegExp('(^| )'+classname+'( |$)');
    var els = node.getElementsByTagName("*");
    for(var i=0,j=els.length; i<j; i++)
        if(re.test(els[i].className))a.push(els[i]);
    return a;
}
var tabs = document.getElementsByClassName(document.body,'tab');

... nhưng IE vẫn thông báo:

Đối tượng không hỗ trợ thuộc tính hoặc phương thức này

Bất kỳ ý tưởng, phương pháp tốt hơn, sửa lỗi?

Tôi không muốn sử dụng bất kỳ giải pháp nào liên quan đến jQuery hoặc "javascript cồng kềnh" khác.

Cập nhật:

Tôi đã nhận nó để làm việc!

Như @joe đã đề cập , hàm không phải là một phương thức của document.

Vì vậy, mã làm việc sẽ giống như sau:

function getElementsByClassName(node, classname) {
    var a = [];
    var re = new RegExp('(^| )'+classname+'( |$)');
    var els = node.getElementsByTagName("*");
    for(var i=0,j=els.length; i<j; i++)
        if(re.test(els[i].className))a.push(els[i]);
    return a;
}
var tabs = getElementsByClassName(document.body,'tab');


... Ngoài ra, nếu bạn chỉ cần hỗ trợ IE8 + thì điều này sẽ hoạt động:

if(!document.getElementsByClassName) {
    document.getElementsByClassName = function(className) {
        return this.querySelectorAll("." + className);
    };
    Element.prototype.getElementsByClassName = document.getElementsByClassName;
}

Sử dụng nó giống như bình thường:

var tabs = document.getElementsByClassName('tab');

2
Bạn có chắc chắn bản cập nhật của bạn là đúng? Nó không phải là var tabs = getElementsByClassName (document.body, 'tab'); ** thông báo tôi đã xóa document.getEle ... **
Anthony

Những ví dụ cuối cùng của bạn có đúng không? Bạn đang chuyển vào '.tab' nhưng nó không phải là không có dấu chấm vì phương thức bên trong của bạn thêm dấu chấm và nếu đó là IE9 + thì nó cũng không có dấu chấm? Nó không phải là var tabs = document.getElementsByClassName ('tab') ;? Và tại sao bạn có dấu "hoặc" khi hai ví dụ cuối cùng giống nhau? Chắc chắn là tôi đang thiếu gì đó.
BoBoCoding

@BoBoCoding đã sửa.
Web_Designer

Câu trả lời:


56

Nó không phải là một phương pháp tài liệu:

function getElementsByClassName(node, classname) {
    var a = [];
    var re = new RegExp('(^| )'+classname+'( |$)');
    var els = node.getElementsByTagName("*");
    for(var i=0,j=els.length; i<j; i++)
        if(re.test(els[i].className))a.push(els[i]);
    return a;
}

tabs = getElementsByClassName(document.body,'tab');  // no document

Bạn đang thử nghiệm trên jsFiddle.net hay máy chủ / máy của riêng bạn?
Joe

@inquisitive_web_developer - bạn gặp lỗi gì bây giờ? Nó đang phá vỡ dòng nào?
nnnnnn 14/09/11

17

bạn có thể tạo chức năng cho các trình duyệt cũ hơn

if (typeof document.getElementsByClassName!='function') {
    document.getElementsByClassName = function() {
        var elms = document.getElementsByTagName('*');
        var ei = new Array();
        for (i=0;i<elms.length;i++) {
            if (elms[i].getAttribute('class')) {
                ecl = elms[i].getAttribute('class').split(' ');
                for (j=0;j<ecl.length;j++) {
                    if (ecl[j].toLowerCase() == arguments[0].toLowerCase()) {
                        ei.push(elms[i]);
                    }
                }
            } else if (elms[i].className) {
                ecl = elms[i].className.split(' ');
                for (j=0;j<ecl.length;j++) {
                    if (ecl[j].toLowerCase() == arguments[0].toLowerCase()) {
                        ei.push(elms[i]);
                    }
                }
            }
        }
        return ei;
    }
}

14
function getElementsByClassName(className) {
if (document.getElementsByClassName) { 
  return document.getElementsByClassName(className); }
else { return document.querySelectorAll('.' + className); } }

Khá chắc chắn rằng điều này giống với chức năng của Leonid nhưng điều này sử dụng document.getElementsByClassNamekhi nó có thể.


10

Bạn thực sự không thể sao chép getElementsByClassName, bởi vì nó trả về một nodeList, và vì vậy giá trị của nó vẫn tồn tại và cập nhật với tài liệu.

Bạn có thể trả về một Mảng tĩnh gồm các phần tử có cùng tên lớp - nhưng nó sẽ không 'biết' khi tài liệu thay đổi.

(Sẽ không cần quá nhiều thứ như vậy để làm cho một thư viện trông mỏng manh ...)

function getArrayByClassNames(classes, pa){
    if(!pa) pa= document;
    var C= [], G;
    if(pa.getElementsByClassName){
        G= pa.getElementsByClassName(classes);
        for(var i= 0, L= G.length; i<L; i++){
            C[i]= G[i];
        }
    }
    else{
        classes= classes.split(/\s+/);
        var who, cL= classes.length,
        cn, G= pa.getElementsByTagName('*'), L= G.length;
        for(var i= 0; i<cL; i++){
            classes[i]= RegExp('\\b'+classes[i]+'\\b');
        }
        classnameLoop:
        while(L){
            who= G[--L];
            cn= who.className;
            if(cn){
                for(var i= 0; i<cL; i++){
                    if(classes[i].test(cn)== false) {
                        continue classnameLoop;
                    }
                }
                C.push(who);
            }
        }
    }
    return C;
}

//Thí dụ

var A = getArrayByClassNames ('sideBar cục bộ')


3
+1 để lưu ý rằng không giống như thực getElementsByClassName, các bản hack tương thích (bao gồm querySelectorAll) cung cấp ảnh chụp nhanh tĩnh, không phải bộ sưu tập trực tiếp.
Søren Løvborg

9

IE8:

document.getElementsByClassName = function (className) {
    return document.querySelectorAll('.' + className)
}

1
Không hoạt động trên IE9 của tôi: "Đối tượng không hỗ trợ thuộc tính hoặc phương thức 'querySelectorAll'"
Phil

0
function _getClass(whatEverClasNameYouWant){
var a=document.getElementsByTagName('*');
   for(b in a){
      if((' '+a[b].className+' ').indexOf(' '+whatEverClasNameYouWant+' ')>-1){
      return a[b];
      }
   }
}

0

Tôi chỉ muốn cải thiện querySelectorAlldự phòng cho IE8.

Giống như những người khác đã trả lời, cách đơn giản là thêm hàm vào Element.prototypevới

this.querySelectorAll('.' + className);

Nhưng có một số vấn đề:

  • Nó không hoạt động với các chuỗi không bị xóa (ở đầu).
  • Nó không hoạt động với nhiều lớp.
  • Nó không làm việc với các nhân vật đẳng cấp "lạ" ( /, $, *, vv)
  • Nó không hoạt động với các lớp bắt đầu bằng một chữ số (số nhận dạng không hợp lệ)

Điều đó có nghĩa là phải có một số "sửa chữa", ví dụ:

"abcd"     ->  ".abcd"
"a   b cd" ->  ".a.b.cd"
"   a b  " ->  ".a.b  "
"a/b$c d"  ->  ".a\/b\$c.d"
"1234"     ->  ".\000031234"

Mã:

this.querySelectorAll(className
    .replace(/(?=[^ \w])/g, '\\')   // Escape non-word characters
    .replace(/\b\d/g, '\\00003$&')  // Escape digits at the beginning
    .replace(/(^| +)(?!$| )/g, '.') // Add "." before classes, removing spaces
);

1
Chức năng cũng có thể được thêm HTMLDocument.prototypevào để sử dụng với document.
Oriol
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.