티스토리 뷰

Element.classList (원문 바로가기)


Element.classList는 읽기 전용 속성으로 DOMTokenList를 실시간으로 반영한다. (즉, 해당 속성 값을 변경하면, 재 표현된다.)


classList를 사용하면 각각의 class 요소들에 접근 또는 편집을 할 수 있다. classList의 내용물은 element.className의 값을 공백(띄어쓰기)로 구분한 list 형식이다.


Syntax


var elementClasses = elementNodeReference.classList;


elementClasses 는 elementNodeReference의 class 속성을 DOMTokenList로 재구성한 것이다. 만일 class 속성이 설정되어 있지 않거나, 비어있다면 elementClasses.length 는 0을 리턴한다. element.classList 자체는 읽기 전용이더라도 add() 와 remove() 메서드들을 사용해서 그것을 수정할 수 있다.


Method

add(String[, String])

 명시된 class 값을 추가한다. 만일 이미 존재하는 값을 넣으려고 한다면 넣으려는 값이 무시된다.


remove(String[, String])

 명시된 class 값을 지운다.


item( Number )

 콜렉션에서 전달된 Number(Index)에 위치한 class 값을 리턴한다.


toggle( String[, force] )

 인자 하나만 사용했을 때: class 값을 토글(껏다 켰다). 만일 class 가 있으면 지우고, false를 리턴한다. 그렇지 않다면 추가하고 true를 리턴한다.


 인자 두개를 사용했을 때: 두번째 인자를 true로 전달하면 명시된 class 값을 추가한다. 그리고 false로 전달하면 지운다.


contains( String )

 전달한 class 값이 그 엘리먼트의 class 속성에 존재하는지 확인한다. 있으면 true를 없으면 false를 리턴한다.


Examples


```javascript

// div is an object reference to a <div> element with class="foo bar"
div.classList.remove("foo");
div.classList.add("anotherclass");

// if visible is set remove it, otherwise add it
div.classList.toggle("visible");

//  add/remove visible, depending on test conditional, i less than 10
div.classList.toggle("visible", i < 10 );

alert(div.classList.contains("foo"));

div.classList.add("foo","bar"); //add multiple classes

```


Note! 파이어폭스 26 이전 버전에서는 add/remove/toggle 메서드들이 구현이 안되어 있어요.



Javascript shim for other implementaions

Note! 이 shim은 IE 8 이하(미만? 확인이 필요하다.) 에서는 동작하지 않아요.


```javascript

/* 
 * classList.js: Cross-browser full element.classList implementation.
 * 2014-07-23
 *
 * By Eli Grey, http://eligrey.com
 * Public Domain.
 * NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
 */

/*global self, document, DOMException */

/*! @source http://purl.eligrey.com/github/classList.js/blob/master/classList.js*/

if ("document" in self) {

// Full polyfill for browsers with no classList support
if (!("classList" in document.createElement("_"))) {

(function (view) {

"use strict";

if (!('Element' in view)) return;

var
    classListProp = "classList"
  , protoProp = "prototype"
  , elemCtrProto = view.Element[protoProp]
  , objCtr = Object
  , strTrim = String[protoProp].trim || function () {
    return this.replace(/^\s+|\s+$/g, "");
  }
  , arrIndexOf = Array[protoProp].indexOf || function (item) {
    var
        i = 0
      , len = this.length
    ;
    for (; i < len; i++) {
      if (i in this && this[i] === item) {
        return i;
      }
    }
    return -1;
  }
  // Vendors: please allow content code to instantiate DOMExceptions
  , DOMEx = function (type, message) {
    this.name = type;
    this.code = DOMException[type];
    this.message = message;
  }
  , checkTokenAndGetIndex = function (classList, token) {
    if (token === "") {
      throw new DOMEx(
          "SYNTAX_ERR"
        , "An invalid or illegal string was specified"
      );
    }
    if (/\s/.test(token)) {
      throw new DOMEx(
          "INVALID_CHARACTER_ERR"
        , "String contains an invalid character"
      );
    }
    return arrIndexOf.call(classList, token);
  }
  , ClassList = function (elem) {
    var
        trimmedClasses = strTrim.call(elem.getAttribute("class") || "")
      , classes = trimmedClasses ? trimmedClasses.split(/\s+/) : []
      , i = 0
      , len = classes.length
    ;
    for (; i < len; i++) {
      this.push(classes[i]);
    }
    this._updateClassName = function () {
      elem.setAttribute("class", this.toString());
    };
  }
  , classListProto = ClassList[protoProp] = []
  , classListGetter = function () {
    return new ClassList(this);
  }
;
// Most DOMException implementations don't allow calling DOMException's toString()
// on non-DOMExceptions. Error's toString() is sufficient here.
DOMEx[protoProp] = Error[protoProp];
classListProto.item = function (i) {
  return this[i] || null;
};
classListProto.contains = function (token) {
  token += "";
  return checkTokenAndGetIndex(this, token) !== -1;
};
classListProto.add = function () {
  var
      tokens = arguments
    , i = 0
    , l = tokens.length
    , token
    , updated = false
  ;
  do {
    token = tokens[i] + "";
    if (checkTokenAndGetIndex(this, token) === -1) {
      this.push(token);
      updated = true;
    }
  }
  while (++i < l);

  if (updated) {
    this._updateClassName();
  }
};
classListProto.remove = function () {
  var
      tokens = arguments
    , i = 0
    , l = tokens.length
    , token
    , updated = false
    , index
  ;
  do {
    token = tokens[i] + "";
    index = checkTokenAndGetIndex(this, token);
    while (index !== -1) {
      this.splice(index, 1);
      updated = true;
      index = checkTokenAndGetIndex(this, token);
    }
  }
  while (++i < l);

  if (updated) {
    this._updateClassName();
  }
};
classListProto.toggle = function (token, force) {
  token += "";

  var
      result = this.contains(token)
    , method = result ?
      force !== true && "remove"
    :
      force !== false && "add"
  ;

  if (method) {
    this[method](token);
  }

  if (force === true || force === false) {
    return force;
  } else {
    return !result;
  }
};
classListProto.toString = function () {
  return this.join(" ");
};

if (objCtr.defineProperty) {
  var classListPropDesc = {
      get: classListGetter
    , enumerable: true
    , configurable: true
  };
  try {
    objCtr.defineProperty(elemCtrProto, classListProp, classListPropDesc);
  } catch (ex) { // IE 8 doesn't support enumerable:true
    if (ex.number === -0x7FF5EC54) {
      classListPropDesc.enumerable = false;
      objCtr.defineProperty(elemCtrProto, classListProp, classListPropDesc);
    }
  }
} else if (objCtr[protoProp].__defineGetter__) {
  elemCtrProto.__defineGetter__(classListProp, classListGetter);
}

}(self));

} else {
// There is full or partial native classList support, so just check if we need
// to normalize the add/remove and toggle APIs.

(function () {
  "use strict";

  var testElement = document.createElement("_");

  testElement.classList.add("c1", "c2");

  // Polyfill for IE 10/11 and Firefox <26, where classList.add and
  // classList.remove exist but support only one argument at a time.
  if (!testElement.classList.contains("c2")) {
    var createMethod = function(method) {
      var original = DOMTokenList.prototype[method];

      DOMTokenList.prototype[method] = function(token) {
        var i, len = arguments.length;

        for (i = 0; i < len; i++) {
          token = arguments[i];
          original.call(this, token);
        }
      };
    };
    createMethod('add');
    createMethod('remove');
  }

  testElement.classList.toggle("c3", false);

  // Polyfill for IE 10 and Firefox <24, where classList.toggle does not
  // support the second argument.
  if (testElement.classList.contains("c3")) {
    var _toggle = DOMTokenList.prototype.toggle;

    DOMTokenList.prototype.toggle = function(token, force) {
      if (1 in arguments && !this.contains(token) === !force) {
        return force;
      } else {
        return _toggle.call(this, token);
      }
    };

  }

  testElement = null;
}());

}

}

```


Browser 호환성

원문을 참조하시면 될거 같아요.


매번 javascript 를 통해 DOM 을 제어할 때마다 이 Class 속성값을 편집하는게 상당히 귀찮았는데 덕분에 좋은걸 알게되었네요.


jQuery를 쓰면 좋지만, 공부도 할겸, 보다 Javascript Core Engine을 이해할겸 겸사겸사 하다보니 스스로 고생하는 격이네요. ㅎㅎ


그냥 지나치려다가 번역이 안되어 있는거 같아 발번역을 시도해보았습니다.


오타나 오역이 있으면 욕을 해주시면서 가르침을 내려주시면 감사하겠습니다.