Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Code with classList does not work in IE?

I'm using the following code, but having it fail in IE. The message is:

Unable to get value of the property 'add': object is null or undefined"

I assume this is just an IE support issue. How would you make the following code work in IE?

Any ideas?

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);
like image 256
Wesley Avatar asked Nov 11 '11 18:11

Wesley


People also ask

Does ie11 support classList?

IE 11 doesn't support assigning to classList · Issue #3808 · Fyrd/caniuse · GitHub.

How do I toggle a classList in Javascript?

classList: This property returns the class name(s) of the element as a DOMTokenList object. This object has some well known methods including contains(), add(), remove(), toggle(). contains(): This method returns a boolean value indicating if a particular class name is present or not.

What does the element classList toggle () method do?

toggle() The toggle() button is used for toggling classes to the element. It means adding a new class or removing the existing classes.

What does element classList do?

The Element. classList is a read-only property that returns a live DOMTokenList collection of the class attributes of the element. This can then be used to manipulate the class list. Using classList is a convenient alternative to accessing an element's list of classes as a space-delimited string via element.


3 Answers

The classList property is not supported by IE9 and lower. IE10+ supports it though.
Use className += " .." instead. Note: Do not omit the space: class names should be added in a white-space separated list.

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);
like image 197
Rob W Avatar answered Oct 07 '22 02:10

Rob W


As mentioned by othes, classList is not supported by IE9 and older. As well as Alex's alternative above, there are a couple of polyfills which aim to be a drop-in replacement, i.e. just include these in your page and IE should just work (famous last words!).

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

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

like image 26
tagawa Avatar answered Oct 07 '22 02:10

tagawa


In IE 10 & 11, The classList property is defined on HTMLElement.prototype.

In order to get it to work on SVG-elements, the property should be defined on Element.prototype, like it has been on other browsers.

A very small fix would be copying the exact propertyDescriptor from HTMLElement.prototype to 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'));
    }
}
  • We need to copy the descriptor, since Element.prototype.classList = HTMLElement.prototype.classList will throw Invalid calling object
  • The first check prevents overwriting the property on browsers which support is natively.
  • The second check is prevents errors on IE versions prior to 9, where HTMLElement is not implemented yet, and on IE9 where classList is not implemented.

For IE 8 & 9, use the following code, I also included a (minified) polyfill for Array.prototype.indexOf, because IE 8 does not support it natively (polyfill source: 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;
    }
});
like image 11
Kevin Drost Avatar answered Oct 07 '22 02:10

Kevin Drost