classListを含むコードはIEで機能しませんか?


83

次のコードを使用していますが、IEで失敗します。メッセージは次のとおりです。

プロパティの値を取得できません '追加':オブジェクトがnullまたは未定義です "

これはIEサポートの問題だと思います。次のコードをIEでどのように機能させますか?

何か案は?

var img = new Image();
img.src = '/image/file.png';
img.title = 'this is a title';
img.classList.add("profilePic");
var div = document.createElement("div");
div.classList.add("picWindow");
div.appendChild(img);
content.appendChild(div);

5
IEにはclassListがないため、nullまたは未定義です
Esailija 2011

2
jQueryを使用しますか?
arb 2011

1
@ Zero21xxx気にしないでください。ただし、標準のJSの代わりにJQueryオブジェクトを使用するには、上記のすべてのコードを書き直す必要があります。
ウェズリー


1
@alexあなたのブログ投稿は更新で行うことができます。まず、最終的なリンク(MDN)が間違っている、querySelectorでなければなりませんclassList。次に、この.removeメソッドには不要な正規表現が含まれています。この正規表現を使用すると、ご存知のとおり、バグが発生します。スペースの前と接尾辞はすでにあるので、単純なもの.replace(' ' + className + ' ', ' ')で十分です(さらに、「有効なclassNameには特別な正規表現文字を含めないでください。」という注釈は正しくありません。仕様を参照してください(HTML4にも当てはまります))
Rob W

回答:


92

このclassListプロパティは、IE9以下ではサポートされていません。IE10 +はそれをサポートしています。代わりに
使用してくださいclassName += " .."。注:スペースを省略しないでください。クラス名は空白で区切られたリストに追加する必要があります。

var img = new Image();
img.src = '/image/file.png';
img.title = 'this is a title';
img.className += " profilePic"; // Add profilePic class to the image

var div = document.createElement("div");
div.className += " picWindow";  // Add picWindow class to the div
div.appendChild(img);
content.appendChild(div);

3
@MikeChristensenclassName属性は常に存在します。空の文字列で初期化されます。コードのメンテナンスを容易にするために、を使用+=してクラス名を追加することをお勧めします。
ロブW

2
strictモードでは、classNameは読み取り専用であるため、これによりエラーが生成されます。
Jason Aller 2014

1
@JasonAllerそれはほとんどありません。DOMclassName要素のプロパティは読み取り/書き込みです。
ロブW

47
IE11はまだclassListのバグであり、SVG要素のclassListをサポートしていません。
codenamezero

1
また、jQueryはSVG要素にもクラスを追加できないため、上記のソリューションは、SVGを操作する場合にのみ可能なことのように見えます。
Senthe 2016年

26

他の人が述べたように、classListIE9以前ではサポートされていません。上記のAlexの代替案に加えて、ドロップイン置換を目的としたポリフィルがいくつかあります。つまり、これらをページに含めるだけで、IEが機能するはずです(有名な最後の言葉です!)。

https://github.com/eligrey/classList.js/blob/master/classList.js

https://gist.github.com/devongovett/1381839


11
IE 11を使用していますが、classListが機能していないようです(Chromeで動作します)
john ktejik 2014年

1
それは奇妙です-caniuse.comは、IE10 +からサポートされるべきだと言っています。Twitterで@TheWebJustWorksに質問するか、webcompat.comで問題を提出することをお勧めします
tagawa

3
@johnktejik一度に複数のクラスを追加または削除すると、IE11、Firefox 24-、およびChrome24では機能しません。それはあなたがしていたことでしたか?
mnsth 2015年

1
@BradAdamsここここ。CaniuseとMDNにもレポートがあります。ただし、これらの問題はすべてMicrosoftEdgeで修正されています。
mnsth 2017

2
classListはまだSVG要素でサポートされていません、これらのポリフィルはトリックを行います
Shoplifter.Doe

10
    /**
 * Method that checks whether cls is present in element object.
 * @param  {Object} ele DOM element which needs to be checked
 * @param  {Object} cls Classname is tested
 * @return {Boolean} True if cls is present, false otherwise.
 */
function hasClass(ele, cls) {
    return ele.getAttribute('class').indexOf(cls) > -1;
}

/**
 * Method that adds a class to given element.
 * @param  {Object} ele DOM element where class needs to be added
 * @param  {Object} cls Classname which is to be added
 * @return {null} nothing is returned.
 */
function addClass(ele, cls) {
    if (ele.classList) {
        ele.classList.add(cls);
    } else if (!hasClass(ele, cls)) {
        ele.setAttribute('class', ele.getAttribute('class') + ' ' + cls);
    }
}

/**
 * Method that does a check to ensure that class is removed from element.
 * @param  {Object} ele DOM element where class needs to be removed
 * @param  {Object} cls Classname which is to be removed
 * @return {null} Null nothing is returned.
 */
function removeClass(ele, cls) {
    if (ele.classList) {
        ele.classList.remove(cls);
    } else if (hasClass(ele, cls)) {
        ele.setAttribute('class', ele.getAttribute('class').replace(cls, ' '));
    }
}

2
+1、しかし:私はele.getAttribute('class')いくつかのケースでnullを返しました(多分クラス属性がまだ設定されていない場合?)-単純なifステートメントがそれを解決しました。
ジェッペ2018

8

これをチェックしてください

Object.defineProperty(Element.prototype, 'classList', {
    get: function() {
        var self = this, bValue = self.className.split(" ")

        bValue.add = function (){
            var b;
            for(i in arguments){
                b = true;
                for (var j = 0; j<bValue.length;j++)
                    if (bValue[j] == arguments[i]){
                        b = false
                        break
                    }
                if(b)
                    self.className += (self.className?" ":"")+arguments[i]
            }
        }
        bValue.remove = function(){
            self.className = ""
            for(i in arguments)
                for (var j = 0; j<bValue.length;j++)
                    if(bValue[j] != arguments[i])
                        self.className += (self.className?" " :"")+bValue[j]
        }
        bValue.toggle = function(x){
            var b;
            if(x){
                self.className = ""
                b = false;
                for (var j = 0; j<bValue.length;j++)
                    if(bValue[j] != x){
                        self.className += (self.className?" " :"")+bValue[j]
                        b = false
                    } else b = true
                if(!b)
                    self.className += (self.className?" ":"")+x
            } else throw new TypeError("Failed to execute 'toggle': 1 argument required")
            return !b;
        }

        return bValue; 
    },
    enumerable: false
})

そしてclassListは機能します!

document.getElementsByTagName("div")[0].classList
["aclass"]

document.getElementsByTagName("div")[0].classList.add("myclass")

document.getElementsByTagName("div")[0].className
"aclass myclass"

それで全部です!


私は初心者です。上記はどこに配置しますか?<script>または<style>で?
Fandango68

このコードを問題のあるコードのすぐ上のスクリプトブロックに挿入しました-非常にうまく機能します。ありがとう。
robnick 2016年

1
よくできました。残念ながら、これはすべての場合に機能するわけではありませんが、これは見つかりました:github.com/remy/polyfills/blob/…–
Michiel

7

IE 10および11では、classListプロパティはHTMLElement.prototypeで定義されています。

SVG要素で機能させるには、他のブラウザーと同様に、プロパティをElement.prototypeで定義する必要があります。

非常に小さな修正は、正確なpropertyDescriptorをHTMLElement.prototypeからElement.prototypeにコピーすることです。

if (!Object.getOwnPropertyDescriptor(Element.prototype,'classList')){
    if (HTMLElement&&Object.getOwnPropertyDescriptor(HTMLElement.prototype,'classList')){
        Object.defineProperty(Element.prototype,'classList',Object.getOwnPropertyDescriptor(HTMLElement.prototype,'classList'));
    }
}
  • Element.prototype.classList = HTMLElement.prototype.classListスローするので、記述子をコピーする必要がありますInvalid calling object
  • 最初のチェックは、ネイティブにサポートされているブラウザでプロパティが上書きされるのを防ぎます。
  • 2番目のチェックは、HTMLElementがまだ実装されていない9より前のバージョンのIEと、classListが実装されていないIE9でのエラーを防ぐことです。

IE 8および9の場合、次のコードを使用します。IE8はネイティブでサポートしていないため、Array.prototype.indexOfの(縮小された)ポリフィルも含めました(ポリフィルソース:Array.prototype.indexOf

//Polyfill Array.prototype.indexOf
Array.prototype.indexOf||(Array.prototype.indexOf=function (value,startIndex){'use strict';if (this==null)throw new TypeError('array.prototype.indexOf called on null or undefined');var o=Object(this),l=o.length>>>0;if(l===0)return -1;var n=startIndex|0,k=Math.max(n>=0?n:l-Math.abs(n),0)-1;function sameOrNaN(a,b){return a===b||(typeof a==='number'&&typeof b==='number'&&isNaN(a)&&isNaN(b))}while(++k<l)if(k in o&&sameOrNaN(o[k],value))return k;return -1});

// adds classList support (as Array) to Element.prototype for IE8-9
Object.defineProperty(Element.prototype,'classList',{
    get:function(){
        var element=this,domTokenList=(element.getAttribute('class')||'').replace(/^\s+|\s$/g,'').split(/\s+/g);
        if (domTokenList[0]==='') domTokenList.splice(0,1);
        function setClass(){
            if (domTokenList.length > 0) element.setAttribute('class', domTokenList.join(' ');
            else element.removeAttribute('class');
        }
        domTokenList.toggle=function(className,force){
            if (force!==undefined){
                if (force) domTokenList.add(className);
                else domTokenList.remove(className);
            }
            else {
                if (domTokenList.indexOf(className)!==-1) domTokenList.splice(domTokenList.indexOf(className),1);
                else domTokenList.push(className);
            }
            setClass();
        };
        domTokenList.add=function(){
            var args=[].slice.call(arguments)
            for (var i=0,l=args.length;i<l;i++){
                if (domTokenList.indexOf(args[i])===-1) domTokenList.push(args[i])
            };
            setClass();
        };
        domTokenList.remove=function(){
            var args=[].slice.call(arguments)
            for (var i=0,l=args.length;i<l;i++){
                if (domTokenList.indexOf(args[i])!==-1) domTokenList.splice(domTokenList.indexOf(args[i]),1);
            };
            setClass();
        };
        domTokenList.item=function(i){
            return domTokenList[i];
        };
        domTokenList.contains=function(className){
            return domTokenList.indexOf(className)!==-1;
        };
        domTokenList.replace=function(oldClass,newClass){
            if (domTokenList.indexOf(oldClass)!==-1) domTokenList.splice(domTokenList.indexOf(oldClass),1,newClass);
            setClass();
        };
        domTokenList.value = (element.getAttribute('class')||'');
        return domTokenList;
    }
});

最初のコードはそれをうまく切り取ったが、2つの閉じ括弧が欠けていた)
superdweebie 2018年

@superdweebie、気づいてくれてありがとう。私は私の答えを修正しました
Kevin Drost 2018年

3

Explorer 11では、classList.addは単一の値でのみ機能します。

Element.classList.add("classOne", "classTwo");

この場合、エクスプローラーは最初のクラスのみを追加し、2番目のクラスを無視します。だからする必要があります:

Element.classList.add("classOne");
Element.classList.add("classTwo");

0

classListIE <9ではサポートされていません。jQuery.addClassまたはhttps://developer.mozilla.org/en-US/docs/Web/API/Element/classListにあるようなポリフィルを使用してください。


1
これに反対した人へ:これは答えが投稿されたときに真実であり、IE 9だけがそれをサポートし始めました
Juan Mendes

2
質問がjQueryを求めていなかったので、それが反対票を投じられたと推測するのは危険です。Javascriptライブラリ全体の使用を伴わない問題を回避する方法があります。
ヴィンセント・マクナブ2014

4
-1:うん...右...ひどく模倣するために100キロバイトのライブラリを追加することができますclassList機能
tereško

1
@tereškoまだjQueryを使用していない場合は、「またはそのようなもの」と表示されます。受け入れられた回答は、同じクラス名がすでに存在するかどうかをチェックしないため、同じクラス名を2回追加する可能性があることに注意してください。
フアンメンデス
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.