Javascript document.getElementsByClassName совместимость с IE
Каков наилучший метод для извлечения массива элементов, имеющих определенный класс?
Я бы использовал document.getElementsByClassName, но IE не поддерживает его.
Итак, я попробовал решение Джонатана Снука:
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');
... но IE все еще говорит:
Объект не поддерживает это свойство или метод
Любые идеи, лучшие методы, исправления ошибок?
Я бы предпочел не использовать какие-либо решения, связанные с jQuery или другим "громоздким javascript".
Update:
Я получил его для работы!
Как @joe, упомянутый, функция не является методом document
.
Итак, рабочий код будет выглядеть так:
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');
... Также , если вам нужна только поддержка IE8 +, тогда это будет работать:
if(!document.getElementsByClassName) {
document.getElementsByClassName = function(className) {
return this.querySelectorAll("." + className);
};
Element.prototype.getElementsByClassName = document.getElementsByClassName;
}
Используйте его, как обычно:
var tabs = document.getElementsByClassName('tab');
Ответы
Ответ 1
Это не метод документа:
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
Ответ 2
вы можете создать функцию для старых браузеров
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;
}
}
Ответ 3
function getElementsByClassName(className) {
if (document.getElementsByClassName) {
return document.getElementsByClassName(className); }
else { return document.querySelectorAll('.' + className); } }
Довольно уверен, что это то же самое, что и функция Леонида, но при этом используется document.getElementsByClassName
, когда это возможно.
Ответ 4
Вы не можете реально реплицировать getElementsByClassName, потому что он возвращает nodeList,
и поэтому его значение является живым и обновляется с документом.
Вы можете вернуть статический массив элементов, которые имеют одинаковые имена классов -
но он не будет "знать", когда документ изменится.
(Это не займет слишком много таких вещей, чтобы библиотека выглядела стройной...)
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;
}
//Пример
var A = getArrayByClassNames ('sideBar local')
Ответ 5
IE8:
document.getElementsByClassName = function (className) {
return document.querySelectorAll('.' + className)
}
Ответ 6
function _getClass(whatEverClasNameYouWant){
var a=document.getElementsByTagName('*');
for(b in a){
if((' '+a[b].className+' ').indexOf(' '+whatEverClasNameYouWant+' ')>-1){
return a[b];
}
}
}
Ответ 7
Я просто хочу улучшить резервную копию querySelectorAll
для IE8.
Как и другие, простой способ заключается в добавлении функции к Element.prototype
с помощью
this.querySelectorAll('.' + className);
Но есть некоторые проблемы:
- Он не работает с необработанными строками (в начале).
- Он не работает с несколькими классами.
- Он не работает со "странными" символами класса (
/
, $
, *
и т.д.)
- Он не работает с классами, начинающимися с цифры (недопустимые идентификаторы)
Это означает, что должно быть какое-то "исправление", например:
"abcd" -> ".abcd"
"a b cd" -> ".a.b.cd"
" a b " -> ".a.b "
"a/b$c d" -> ".a\/b\$c.d"
"1234" -> ".\000031234"
Код:
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
);