jQuery RemoveClass підстановка


370

Чи є простий спосіб видалити всі класи, які відповідають, наприклад,

color-*

тому якщо у мене є елемент:

<div id="hello" class="color-red color-brown foo bar"></div>

після вилучення було б

<div id="hello" class="foo bar"></div>

Дякую!


1
Зворотний вираз, як у "прийнятій відповіді", розбивається на межі слова, що не є пробілами. Нижче я розмістив альтернативне рішення. Також дивіться: stackoverflow.com/questions/57812 / ...
sarink

@KabirSarin прийняту відповідь було оновлено, щоб виправити це.
Еміль Бержерон

Відповіді:


679

Функція RemoveClass приймає аргумент функції, починаючи з jQuery 1.4 .

$("#hello").removeClass (function (index, className) {
    return (className.match (/(^|\s)color-\S+/g) || []).join(' ');
});

Приклад наживо: http://jsfiddle.net/xa9xS/1409/


4
Я подумав, що варто відзначити, що це займе провідну пробіл відповідних класів, які не починаються спочатку. Javascript не підтримує позитивний погляд позаду, тому вам доведеться використовувати обробку групи захоплення. Однак це суперечка, оскільки функція removeClass зніме пробіл із рядка класу для вас черезclasses = ( value || "" ).match( rnotwhite ) || [];
eephillip

Мені це рішення найбільше подобається! Як я можу перевірити видалення двох або більше класів? тобто sport-, nav-і color-?
lowtechsun

Як би ви це зробили, щоб відповідати закінченню класу *-color?
Коло Б

3
@lowtechsun ви можете додати у свій регекс так (color-|sport-|nav-). Він буде відповідати color-, або sport-, або nav-. Отже, відповідь вище стала б /(^|\s)(color-|sport-|nav-)\S+/g.
Bogie

1
Прийнята відповідь є правильною, але ідіоматично я б використовував \ b, яке відповідає будь-якій межі слова, а не більш словомовної (^ | \ s). Так, наприклад, для видалення всіх класів, що складаються зі слова магія, за яким слідує негативне ціле число, і лише ті, я б відповідав / / bmagic \ d + \ b /.
CarlEdman

98
$('div').attr('class', function(i, c){
    return c.replace(/(^|\s)color-\S+/g, '');
});

5
Мені це подобається, оскільки це зменшує накладні витрати і стає прямо до точки. Навіщо використовувати клас видалення, коли attr робить роботу краще?
Сердитий Ден

2
я думаю, вам потрібно захистити від порожніх класів ( c is undefined)? Принаймні, коли я спробував це нижче у своєму плагіні на цій сторінці, $('a').stripClass('post', 1)кинув "TypeError: Неможливо викликати метод" замінити "невизначеним"
drzaus

1
@Kobi, так, я не думаю, що можна відфільтрувати атрибут і повернути результат, у якого його немає - $('div[class]')слід повертати лише елементи, мають classвони значення чи ні. тестові сценарії: jsfiddle.net/drzaus/m83mv
drzaus

1
@Kobi - я думаю, я бачу, до чого ти потрапляєш; у крайових випадках, як-от .removeProp('class')або .className=undefinedфільтр [class]все-таки щось повертає, вони просто undefined. Так технічно він все ще має клас (на відміну від цього .removeAttr('class'), тому він порушує вашу функцію, але не мій варіант. Jsfiddle.net/drzaus/m83mv/4
drzaus

1
Додавання швидкого тестування для мене працює:return c && c.replace(/\bcolor-\S+/g, '');
ssmith

50

Я написав плагін, який робить це під назвою alterClass - Видалення класів елементів із відповідним підстановкою. За бажанням додайте класи: https://gist.github.com/1517285

$( '#foo' ).alterClass( 'foo-* bar-*', 'foobar' )

1
Дуже добре, справді ... допомогло мені повторно використовувати якийсь код, з якого мені просто потрібно було видалити Twitter Boostrapтакі класи:$(".search div").children('div').alterClass('span* row-fluid');
Леніел Макаферрі

15

Я узагальнив це у плагіні Jquery, який бере аргумент як аргумент.

Кава:

$.fn.removeClassRegex = (regex) ->
  $(@).removeClass (index, classes) ->
    classes.split(/\s+/).filter (c) ->
      regex.test c
    .join ' '

Javascript:

$.fn.removeClassRegex = function(regex) {
  return $(this).removeClass(function(index, classes) {
    return classes.split(/\s+/).filter(function(c) {
      return regex.test(c);
    }).join(' ');
  });
};

Отже, у цьому випадку використання буде (і кава, і Javascript):

$('#hello').removeClassRegex(/^color-/)

Зауважте, що я використовую Array.filterфункцію, яка не існує в IE <9. Ви можете замість цього використовувати функцію фільтрування Underscore або Google для поліфункції, такої як WTFPL .


11

Якщо ви хочете використовувати його в інших місцях, я пропоную вам розширення. Цей добре працює для мене.

 $.fn.removeClassStartingWith = function (filter) {
    $(this).removeClass(function (index, className) {
        return (className.match(new RegExp("\\S*" + filter + "\\S*", 'g')) || []).join(' ')
    });
    return this;
};

Використання:

$(".myClass").removeClassStartingWith('color');

4

ми можемо отримати всі класи за допомогою .attr("class"), і до масиву, і циклу та фільтра:

var classArr = $("#sample").attr("class").split(" ")
$("#sample").attr("class", "")
for(var i = 0; i < classArr.length; i ++) {
    // some condition/filter
    if(classArr[i].substr(0, 5) != "color") {
        $("#sample").addClass(classArr[i]);
    }
}

демонстрація: http://jsfiddle.net/L2A27/1/


Додано var prefix='color';та змінено ...if (classArr[i].substr(0, prefix.length) != prefix)
Rich C

4

Подібно @ tremby - х відповіді , ось @ Кобі в відповідь як плагін , який буде відповідати або префікси або суфікси.

  • ех) смуги btn-miniі , btn-dangerале не btnколи stripClass("btn-").
  • ех) смуги horsebtnі , cowbtnале не btn-miniабо , btnколиstripClass('btn', 1)

Код:

$.fn.stripClass = function (partialMatch, endOrBegin) {
    /// <summary>
    /// The way removeClass should have been implemented -- accepts a partialMatch (like "btn-") to search on and remove
    /// </summary>
    /// <param name="partialMatch">the class partial to match against, like "btn-" to match "btn-danger btn-active" but not "btn"</param>
    /// <param name="endOrBegin">omit for beginning match; provide a 'truthy' value to only find classes ending with match</param>
    /// <returns type=""></returns>
    var x = new RegExp((!endOrBegin ? "\\b" : "\\S+") + partialMatch + "\\S*", 'g');

    // https://stackoverflow.com/a/2644364/1037948
    this.attr('class', function (i, c) {
        if (!c) return; // protect against no class
        return c.replace(x, '');
    });
    return this;
};

https://gist.github.com/zaus/6734731


1
Для запису я не згоден, що це простіше.
тремтіння

@tremby Вибачте, я мав на увазі простіший у типовому використанні (тобто префікси та суфікси), оскільки вам не доведеться писати регулярні
виразки

3
Я все ще не згоден. За допомогою свого методу ви повинні прочитати документацію і запам'ятати, яке саме значення endOrBeginмає бути. Це не пояснює себе. Що важко написати регулярний вираз? /^match-at-start/і /match-at-end$/відомі кожному розробнику JS. Але кожен по-своєму.
тремтіння

1
@tremby крім регулярних виразів , що просять бути ображеними, що не-регулярний вираз варіант більш точно відповідає існуючій підписи addClass, removeClassі toggleClass, яка , як відомо кожному розробнику JQuery. Що важко з читанням документації? ;)
drzaus

2
Читати документацію немає нічого складного, але, як говорить @tremby, його рішення само собою зрозуміле, тоді як ваше вимагає документації. Рішення, що пояснюються самостійно, простіше використовувати за визначенням.
Франсиско Ходж

2

Для плагіна jQuery спробуйте це

$.fn.removeClassLike = function(name) {
    return this.removeClass(function(index, css) {
        return (css.match(new RegExp('\\b(' + name + '\\S*)\\b', 'g')) || []).join(' ');
    });
};

або це

$.fn.removeClassLike = function(name) {
    var classes = this.attr('class');
    if (classes) {
        classes = classes.replace(new RegExp('\\b' + name + '\\S*\\s?', 'g'), '').trim();
        classes ? this.attr('class', classes) : this.removeAttr('class');
    }
    return this;
};

2

На основі ARS81 «s відповіді (що відповідає тільки іменами класів , починаючи з), ось більш гнучким варіантом. Також hasClass()версія регулярної виразки.

Використання: $('.selector').removeClassRegex('\\S*-foo[0-9]+')

$.fn.removeClassRegex = function(name) {
  return this.removeClass(function(index, css) {
    return (css.match(new RegExp('\\b(' + name + ')\\b', 'g')) || []).join(' ');
  });
};

$.fn.hasClassRegex = function(name) {
  return this.attr('class').match(new RegExp('\\b(' + name + ')\\b', 'g')) !== null;
};

2

Це ефективно видалить усі імена класів, що починається з атрибута prefixвузла class. Інші відповіді не підтримують елементи SVG (станом на написання цього), але це рішення:

$.fn.removeClassPrefix = function(prefix){
    var c, regex = new RegExp("(^|\\s)" + prefix + "\\S+", 'g');
    return this.each(function(){
        c = this.getAttribute('class');
        this.setAttribute('class', c.replace(regex, ''));
    });
};

Чи не було б більш ефективно створити RegExpоб'єкт один раз з кожного зворотного дзвінка?
Еміль Бержерон

1
@EmileBergeron - так, було б! Я
внесу

2

У мене була така ж проблема, і я придумав таке, що використовує метод _.filter підкреслення. Як тільки я виявив, що RemoveClass приймає функцію і надає вам список імен класів, було легко перетворити це на масив і відфільтрувати ім'я класу, щоб повернутися назад до методу removeClass.

// Wildcard removeClass on 'color-*'
$('[class^="color-"]').removeClass (function (index, classes) {
  var
    classesArray = classes.split(' '),
    removeClass = _.filter(classesArray, function(className){ return className.indexOf('color-') === 0; }).toString();

  return removeClass;
});

1
Можете чи ви пояснити , що підкреслення робить в _.filter
Bart

2

Ви також можете це зробити за допомогою ванільного JavaScript за допомогою Element.classList . Не потрібно також використовувати регулярний вираз:

function removeColorClasses(element) { for (let className of Array.from(element.classList)) if (className.startsWith("color-")) element.classList.remove(className); }

Примітка. Зауважте, що ми створюємо Arrayкопію classListпопереднього запуску, це важливо, оскільки classListце живе, DomTokenListяке оновлюватиметься після видалення класів.


1

Ви також можете використовувати classNameвластивість об'єкта DOM елемента:

var $hello = $('#hello');
$('#hello').attr('class', $hello.get(0).className.replace(/\bcolor-\S+/g, ''));

1

Загальна функція, яка видаляє будь-який клас, починаючи з begin:

function removeClassStartingWith(node, begin) {
    node.removeClass (function (index, className) {
        return (className.match ( new RegExp("\\b"+begin+"\\S+", "g") ) || []).join(' ');
    });
}

http://jsfiddle.net/xa9xS/2900/

var begin = 'color-';

function removeClassStartingWith(node, begin) {
    node.removeClass (function (index, className) {
        return (className.match ( new RegExp("\\b"+begin+"\\S+", "g") ) || []).join(' ');
    });
}

removeClassStartingWith($('#hello'), 'color-');

console.log($("#hello")[0].className);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="hello" class="color-red color-brown foo bar"></div>


0

Розбиття регулярних виразів на межі слова \b- не найкраще рішення для цього:

var prefix = "prefix";
var classes = el.className.split(" ").filter(function(c) {
    return c.lastIndexOf(prefix, 0) !== 0;
});
el.className = classes.join(" ");

або як jQuery mixin:

$.fn.removeClassPrefix = function(prefix) {
    this.each(function(i, el) {
        var classes = el.className.split(" ").filter(function(c) {
            return c.lastIndexOf(prefix, 0) !== 0;
        });
        el.className = classes.join(" ");
    });
    return this;
};

0

якщо у вас є більше одного елемента з назвою класу 'example', для видалення класів 'color-' у всіх них ви можете це зробити: [використовуючи jquery]

var objs = $('html').find('.example');
for(index=0 ; index < obj1s.length ; index++){
    objs[index].className = objs[index].className.replace(/col-[a-z1-9\-]*/,'');
}

якщо ви не введете [a-z1-9 -] * у свій регулярний вираз, він не видалить класи, у яких в їхніх назвах є число або "-".


0

Якщо вам просто потрібно видалити останній встановлений колір, вам може підійти наступний.

У моїй ситуації мені потрібно було додати клас кольорів до тегу тіла під час події клацання та видалити останній встановлений колір. У цьому випадку ви зберігаєте поточний колір, а потім шукаєте тег даних, щоб видалити останній заданий колір.

Код:

var colorID = 'Whatever your new color is';

var bodyTag = $('body');
var prevColor = bodyTag.data('currentColor'); // get current color
bodyTag.removeClass(prevColor);
bodyTag.addClass(colorID);
bodyTag.data('currentColor',colorID); // set the new color as current

Можливо, це не саме те, що вам потрібно, але для мене це було, і це було перше питання, яке я подивився, тому подумав, що поділюсь своїм рішенням, якщо це допоможе комусь.


Це тут не має значення. Ви могли б відповісти на власне запитання, оскільки це заохочувальна поведінка на SO.
Еміль Бержерон

@Emile: Це правда. Я можу це зробити, оскільки це не відповідає безпосередньо на початкове запитання. Чи варто залишити цю відповідь або видалити її?
redfox05

На той момент це вже на ваш страх і ризик, воно ще не було визнано проголосованим і не схвалено. Тож ви могли без ризику перенести його на власне питання. Також намагайтеся уникати дублікатів, перевіряючи, чи вже є питання щодо цього.
Еміль Бержерон

0

Альтернативний спосіб підходу до цієї проблеми - використання атрибутів даних, які за своєю природою є унікальними.

Ви б встановили колір елемента: $el.attr('data-color', 'red');

І ви б стилізували це в CSS: [data-color="red"]{ color: tomato; }

Це нівелює необхідність використання класів, що має побічний ефект від необхідності видалення старих класів.

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