Як додати / видалити клас у JavaScript?


75

Оскільки element.classListне підтримується в IE 9 та Safari-5, яке альтернативне рішення між браузерами?

Без фреймворків, будь ласка.

Рішення має працювати принаймні в IE 9 , Safari 5 , FireFox 4, Opera 11.5 та Chrome.

Пов’язані повідомлення (але не містить рішення):

  1. як додати та видалити клас css -

  2. Додавання та видалення класу з анімацією

  3. Додати клас видалення?


6
Я ніколи не зрозумію необхідності коду, сумісного з переглядачами, та відмови використовувати фреймворк. Це їхнє саме призначення. Це все одно, що намагатися з’їсти спагетті, але відмовитися від використання виделки, впевнений, що ви можете обійтись, але це брудно.
— davin

2
@davin існує різниця між фреймворками та прокладками. Прокладки також дійсні.
— Raynos

1
@Raynos, більшу частину того, що ти думаєш, буде лише однією фішкою, закінчується п’ятьма, що призводить до набагато менш ремонтопридатного, менш перевіреного коду, який краще замінити фреймворком.
— davin

4
@davin Вам потрібен лише один підклад. Це називається прокладкою DOM. Тоді ви просто пишете код, що відповідає стандартам. Вам потрібен фреймворк, він називається DOM.
— Raynos

24
@davin, тому що їсти спагетті виделкою не означає, що вам не дозволено розуміти, як працює виделка.
— Pacerier

Відповіді:


15

Одним із способів пограти з класами без фреймворків / бібліотек було б використання властивості Element.className, яке " отримує та встановлює значення атрибута класу вказаного елемента. " (З документації MDN ).
Як @ matías-fidemraizer вже згадано у своїй відповіді, як тільки ви отримаєте рядок класів для вашого елемента, ви можете використовувати будь-які методи, пов'язані з рядками, щоб змінити його.

Ось приклад: якщо
припустити, що у вас є div з ідентифікатором "myDiv" і що ви хочете додати до нього клас "main__section", коли користувач натискає на нього,

window.onload = init;

function init() {
  document.getElementById("myDiv").onclick = addMyClass;
}

function addMyClass() {
  var classString = this.className; // returns the string of all the classes for myDiv
  var newClass = classString.concat(" main__section"); // Adds the class "main__section" to the string (notice the leading space)
  this.className = newClass; // sets className to the new string
}

11
Як це може бути прийнятою відповіддю, тоді питання включає клас "видалити", але ця відповідь ні?
— Мотін,

7
.replace (/ \ bexmaple \ b /, "")
— leafiy

це не працює для елемента svg, створеного за допомогою "createElementNS". Як це можна досягти?
— neoexpert

62

Ось рішення для addClass, removeClass, hasClass у чистому розчині javascript.

Насправді це з http://jaketrent.com/post/addremove-classes-raw-javascript/

function hasClass(ele,cls) {
  return !!ele.className.match(new RegExp('(\\s|^)'+cls+'(\\s|$)'));
}

function addClass(ele,cls) {
  if (!hasClass(ele,cls)) ele.className += " "+cls;
}

function removeClass(ele,cls) {
  if (hasClass(ele,cls)) {
    var reg = new RegExp('(\\s|^)'+cls+'(\\s|$)');
    ele.className=ele.className.replace(reg,' ');
  }
}

33

Я щойно написав це:

function addClass(el, classNameToAdd){
    el.className += ' ' + classNameToAdd;   
}

function removeClass(el, classNameToRemove){
    var elClass = ' ' + el.className + ' ';
    while(elClass.indexOf(' ' + classNameToRemove + ' ') !== -1){
         elClass = elClass.replace(' ' + classNameToRemove + ' ', '');
    }
    el.className = elClass;
}

Думаю, вони працюватимуть у всіх браузерах.


Це не працює, наприклад, якщо ви намагаєтесь видалити єдиний клас з елемента (який не має пробілу з обох сторін свого імені)
— Гарет,

@Gareth, це спрацює. Він вставляє пробіл на кожній стороні в одну лінію з removeClass.
— Пол

6
Це не спрацює. Якщо елемент має клас 'abc', і ви намагаєтесь видалити b, він встановить для нового класу значення 'ac'. Таким чином , ви повинні змінити з ''допомогою ' 'в replaceфункції. Більше того, клас - це зарезервоване ключове слово.
— Балі Бало

1
Я зафіксував ваше рішення на 1. Не використовуйте "клас", що є зарезервованим словом 2. Ваш непрацюючий removeClassметод, який створює безліч безладу після багаторазового використання через те, що пробіли не обрізані. Див. Рішення нижче як відповідь.
— Дрю

Я використав цей код із додаванням цього коду відразу після заяви заміна: while (elClass[0] === " ") elClass = elClass.substr(1); while (elClass[elClass.length - 1] === " ") elClass = elClass.substr(0, elClass.length - 1);Це видалить провідний та кінцевий пробіл, який все ще може бути присутнім
— Філіп Корнеліссен

25

Подивіться на ці лайнери:

  1. Вилучити клас:

    element.classList.remove('hidden');
    
  2. Переключити клас (додає клас, якщо він ще не присутній, і видаляє, якщо він є)

    element.classList.toggle('hidden');
    

Це все! Я зробив тест - 10000 ітерацій. 0,8 с.


Зверніть увагу, що classList не підтримується в IE 9, про що йдеться у запитанні OP
— Уоррен Спенсер

2
хоча воно не задовольняє обмеження, яке було надзвичайно характерним для ОП, я думаю, це питання розглядається багатьма людьми, які сподіваються отримати відповідь на загальне питання без цих конкретних обмежень. Я був дуже радий знайти це, і помітив це лише під час свого другого візиту. Я радий, що зробив - набагато чистіше рішення. Дякую!
— Кайл Бейкер

18

Найпростіший , element.classListякий має remove(name), add(name), toggle(name)і contains(name)методи , і в даний час підтримується всіма основними браузерами .

Для старих браузерів ви змінюєтесь element.className. Ось два помічники:

function addClass(element, className){
    element.className += ' ' + className;   
}

function removeClass(element, className) {
    element.className = element.className.replace(
        new RegExp('( |^)' + className + '( |$)', 'g'), ' ').trim();
}

це не працює для елемента svg, створеного за допомогою "createElementNS". Як це можна досягти?
— neoexpert

10

Прочитайте цю статтю мережі розробників Mozilla:

Оскільки властивість element.className має тип string, ви можете використовувати звичайні функції об’єкта String, знайдені в будь-якій реалізації JavaScript:

  • Якщо ви хочете додати клас, спочатку використовуйте String.indexOf, щоб перевірити, чи присутній клас у className . Якщо його немає, просто об’єднайте порожній символ та нове ім’я класу в цю властивість. Якщо він присутній, нічого не робіть.

  • Якщо ви хочете видалити клас, просто використовуйте String.replace, замінивши "[className]" порожнім рядком. Нарешті, використовуйте String.trimдля видалення порожніх символів на початку та в кінці element.className.


5

Виправлено рішення від @Paulpro

  1. Не використовуйте "клас", оскільки це зарезервоване слово
  2. removeClass функція була порушена, оскільки вона вислуховувалася після багаторазового використання.

`

function addClass(el, newClassName){
    el.className += ' ' + newClassName;   
}

function removeClass(el, removeClassName){
    var elClass = el.className;
    while(elClass.indexOf(removeClassName) != -1) {
        elClass = elClass.replace(removeClassName, '');
        elClass = elClass.trim();
    }
    el.className = elClass;
}

Хіба ви не могли перевірити, чи існує ім'я класу, перш ніж додавати його?
— JoeTidee

if(el.className.indexOf(' ' + className) != -1) return;to addClasswould help
— keaton

4

Рішення полягає в

Шим .classList:

Або використовуйте DOM-прокладку, або використовуйте прокладку Eli Grey нижче

Застереження: я вважаю, що підтримка FF3.6 +, Opera10 +, FF5, Chrome, IE8 +

/*
 * classList.js: Cross-browser full element.classList implementation.
 * 2011-06-15
 *
 * 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 (typeof document !== "undefined" && !("classList" in document.createElement("a"))) {

(function (view) {

"use strict";

var
      classListProp = "classList"
    , protoProp = "prototype"
    , elemCtrProto = (view.HTMLElement || 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.className)
            , classes = trimmedClasses ? trimmedClasses.split(/\s+/) : []
            , i = 0
            , len = classes.length
        ;
        for (; i < len; i++) {
            this.push(classes[i]);
        }
        this._updateClassName = function () {
            elem.className = 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 (token) {
    token += "";
    if (checkTokenAndGetIndex(this, token) === -1) {
        this.push(token);
        this._updateClassName();
    }
};
classListProto.remove = function (token) {
    token += "";
    var index = checkTokenAndGetIndex(this, token);
    if (index !== -1) {
        this.splice(index, 1);
        this._updateClassName();
    }
};
classListProto.toggle = function (token) {
    token += "";
    if (checkTokenAndGetIndex(this, token) === -1) {
        this.add(token);
    } else {
        this.remove(token);
    }
};
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));

}

1
Безумовно, розумний шим. Він працює у FF принаймні до 1,5 (не можна перевірити нижче цього). Це порушує IE7 і нижче. З цієї причини на реальних сайтах він майже марний для чогось важливого. Для реального використання використовуйте фреймворк.
— theazureshadow

@theazureshadow psh, Підтримка Legacy призначена для корпоративних рішень, які піклуються про IE7 за межами корпоративного світу.
— Райнос,

Якщо ви піклуєтесь про 12 відсотків користувачів (приблизно кожного восьмого), які зараз використовують IE7 і нижче (джерело: marketshare.hitslink.com ). Я думаю, що iOS 5 є першою версією iOS, яка також її підтримує, тому на момент публікації жоден користувач iPhone не підтримувався. Розмова про спадщину!
— theazureshadow

1
@theazureshadow meh, IE7 не потребує JavaScript. А мобільні - це зовсім інша гра з м’ячем. (Прокладка повинна працювати на мобільних телефонах)
— Райнос,

Ви маєте рацію щодо мобільних пристроїв. Чи справді підтримка IE7 дійсно залежить від окремих випадків. Більшості людей буде легко варто використовувати фреймворк для згладжування відмінностей браузера - далеко поза межами доступності classList. "IE7 не потребує JavaScript" - надзвичайно сумнівне твердження.
— theazureshadow

3

Покращена версія коду Еміля (з trim ())

function hasClass(ele,cls) {
  return !!ele.className.match(new RegExp('(\\s|^)'+cls+'(\\s|$)'));
}

function addClass(ele,cls) {
  if (!hasClass(ele,cls)) ele.className = ele.className.trim() + " " + cls;
}

function removeClass(ele,cls) {
  if (hasClass(ele,cls)) {
    var reg = new RegExp('(\\s|^)'+cls+'(\\s|$)');
    ele.className = ele.className.replace(reg,' ');
    ele.className = ele.className.trim();
  }
}

2
function addClass(element, classString) {
    element.className = element
        .className
        .split(' ')
        .filter(function (name) { return name !== classString; })
        .concat(classString)
        .join(' ');
}

function removeClass(element, classString) {
    element.className = element
        .className
        .split(' ')
        .filter(function (name) { return name !== classString; })
        .join(' ');
}

2

Про всяк випадок, якщо хтось хотів би мати прототипи, побудовані для елементів, це те, що я використовую, коли мені потрібно маніпулювати класами різних об'єктів:

Element.prototype.addClass = function (classToAdd) {
  var classes = this.className.split(' ')
  if (classes.indexOf(classToAdd) === -1) classes.push(classToAdd)
  this.className = classes.join(' ')
}

Element.prototype.removeClass = function (classToRemove) {
  var classes = this.className.split(' ')
  var idx =classes.indexOf(classToRemove)
  if (idx !== -1) classes.splice(idx,1)
  this.className = classes.join(' ')
}

Використовуйте їх як: document.body.addClass('whatever')абоdocument.body.removeClass('whatever')

Замість body ви також можете використовувати будь-який інший елемент (div, span, ви його називаєте)


0

додати класи css: cssClassesStr += cssClassName;

видалити css-класи: cssClassStr = cssClassStr.replace(cssClassName,"");

додати атрибут "Класи": object.setAttribute("class", ""); //pure addition of this attribute

видалити атрибут: object.removeAttribute("class");


0

Легкий для розуміння спосіб:

// Add class 
DOMElement.className += " one";
// Example:
// var el = document.body;
// el.className += " two"

// Remove class 
function removeDOMClass(element, className) {
    var oldClasses      = element.className,
        oldClassesArray = oldClasses.split(" "),
        newClassesArray = [],
        newClasses;

    // Sort
    var currentClassChecked,
        i;     
    for ( i = 0; i < oldClassesArray.length; i++ ) { 
        // Specified class will not be added in the new array
        currentClassChecked = oldClassesArray[i];
        if( currentClassChecked !== className ) { 
            newClassesArray.push(currentClassChecked);
        }
    }

    // Order 
    newClasses = newClassesArray.join(" ");

    // Apply     
    element.className = newClasses;

    return element;

}
// Example:
// var el = document.body;
// removeDOMClass(el, "two")

https://gist.github.com/sorcamarian/ff8db48c4dbf4f5000982072611955a2

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.