jQuery removeClass подстановочный знак

295

Есть ли простой способ удалить все классы, соответствующие, например,

color-*

поэтому, если у меня есть элемент:

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

после удаления, это будет

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

Спасибо!

  • 0
    Регулярное выражение, как в «принятом ответе», нарушит границы непространственного слова. Я разместил альтернативное решение ниже. Также смотрите: stackoverflow.com/questions/57812/…
  • 0
    @KabirSarin принятый ответ был обновлен, чтобы исправить это.
Показать ещё 1 комментарий
Теги:

15 ответов

490
Лучший ответ

Функция removeClass принимает аргумент функции, поскольку jQuery 1.4.

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

Пример в реальном времени: http://jsfiddle.net/xa9xS/1409/

  • 3
    Я подумал, что стоит отметить, что это позволит захватить лидирующие пробелы соответствующих классов, которые не начинаются с самого начала. Javascript не поддерживает позитивный взгляд назад, поэтому вам придется использовать обходной путь группы захвата. Однако это спорный вопрос, потому что функция removeClass удалит для вас пробелы из строки вашего класса с помощью classes = ( value || "" ).match( rnotwhite ) || [];
  • 0
    Мне больше нравится это решение! Как я могу проверить, удаляются ли два или более классов? т.е. sport- , nav- и color- ?
Показать ещё 5 комментариев
76
$('div').attr('class',
           function(i, c){
              return c.replace(/(^|\s)color-\S+/g, '');
           });
  • 4
    Мне это нравится, так как это уменьшает накладные расходы и сразу переходит к делу. Зачем использовать удалить класс, когда attr делает работу лучше?
  • 2
    я думаю, что вам нужно защитить от пустых классов ( c is undefined )? По крайней мере, когда я попробовал это ниже в моем плагине на этой странице, $('a').stripClass('post', 1) бросил "TypeError: Невозможно вызвать метод replace" of undefined "
Показать ещё 5 комментариев
41

Я написал плагин, который делает это с именем alterClass - удаляет классы элементов с подстановочным знаком. Необязательно добавьте классы: https://gist.github.com/1517285

$( '#foo' ).alterClass( 'foo-* bar-*', 'foobar' )
  • 1
    Очень хорошо, действительно ... помог мне повторно использовать некоторый код, где мне просто нужно было удалить классы Twitter Boostrap такие как: $(".search div").children('div').alterClass('span* row-fluid');
12

Я обобщил это в плагин 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(' ');
  });
};

Итак, для этого случая использование будет (и Coffee, и Javascript):

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

Обратите внимание, что я использую функцию Array.filter, которая не существует в IE < 9. Вы могли бы использовать функцию фильтра поддеревьев или Google для polyfill, например this WTFPL one.

4

Подобно @tremby answer, вот @Kobi answer как плагин, который будет соответствовать префиксам или суффиксы.

  • ex) strips btn-mini и btn-danger, но не btn, когда stripClass("btn-").
  • ex) полосы 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');

    // /questions/25038/jquery-removeclass-wildcard/182354#182354
    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
    Для справки, я не согласен, что это проще.
  • 0
    @tremby извините, я имел в виду более простое в типичном использовании (то есть префиксы и суффиксы), так как вам не нужно каждый раз писать регулярное выражение
Показать ещё 3 комментария
3

Если вы хотите использовать его в других местах, я предлагаю вам расширение. Это хорошо работает для меня.

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

Использование:

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

Это эффективно удалит все имена классов, начинающиеся с prefix из атрибута node 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, ''));
    });
};
  • 0
    Не будет ли эффективнее создать объект RegExp один раз из каждого обратного вызова?
  • 1
    @EmileBergeron - да, это будет! Я внесу изменения
2

На основе ARS81 answer (который совпадает только с именами классов, начинающихся с), здесь больше гибкая версия. Также существует версия hasClass() regex.

Использование: $('.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;
};
  • 0
    Это не будет работать с элементами SVG
1

Для плагина 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;
};
1

У меня была такая же проблема, и я придумал следующее, использующее метод underscore _.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
1

мы можем получить все классы с помощью .attr("class"), а в Array и цикл и фильтр:

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]);
    }
}

demo: http://jsfiddle.net/L2A27/1/

  • 0
    Добавлен var prefix='color'; и изменилось ... if (classArr[i].substr(0, prefix.length) != prefix)
1

Вы также можете использовать свойство className объекта DOM элемента:

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

Если вам просто нужно удалить последний заданный цвет, вам может подойти следующее.

В моей ситуации мне нужно было добавить класс цвета в тег body в событии клика и удалить последний цвет, который был установлен. В этом случае вы сохраняете текущий цвет, а затем просматриваете тег данных, чтобы удалить последний заданный цвет.

код:

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, на который я смотрел, поэтому подумал, что поделюсь своим решением, если оно кому-то поможет.

  • 0
    Это не имеет значения здесь. Вы могли бы ответить на свой вопрос, так как в SO это поощряется.
  • 0
    @Emile: это правда. Я мог бы сделать это, поскольку он не отвечает непосредственно на исходный вопрос. Должен ли я оставить этот ответ или удалить его?
Показать ещё 1 комментарий
0

если у вас есть несколько элементов, имеющих имя класса 'example', чтобы удалить классы "color" во всех них, вы можете сделать это: [using 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

Расщепление регулярных выражений на границе слова \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;
};

Ещё вопросы

Сообщество Overcoder
Наверх
Меню