jQuery wildClass ký tự đại diện


370

Có cách nào dễ dàng để loại bỏ tất cả các lớp phù hợp, ví dụ,

color-*

vì vậy nếu tôi có một yếu tố:

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

sau khi gỡ bỏ, nó sẽ là

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

Cảm ơn!


1
Một regex như trong "câu trả lời được chấp nhận" sẽ phá vỡ các ranh giới từ ngoài không gian. Tôi đã đăng một giải pháp thay thế dưới đây. Xem thêm: stackoverflow.com/questions/57812/ Lời
sarink

@KabirSarin câu trả lời được chấp nhận đã được cập nhật để sửa lỗi này.
Emile Bergeron

Câu trả lời:


679

Hàm removeClass nhận một đối số hàm kể từ jQuery 1.4 .

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

Ví dụ trực tiếp: http://jsfiddle.net/xa9xS/1409/


4
Tôi nghĩ rằng đáng chú ý là điều này sẽ chiếm được một khoảng trắng hàng đầu của các lớp phù hợp không bắt đầu ngay từ đầu. Javascript không hỗ trợ giao diện tích cực, do đó bạn sẽ phải sử dụng cách giải quyết nhóm chụp. Tuy nhiên, đây là một mô hình, bởi vì hàm removeClass sẽ loại bỏ khoảng trắng khỏi chuỗi lớp của bạn cho bạn thông quaclasses = ( value || "" ).match( rnotwhite ) || [];
eephillip

Tôi thích giải pháp này nhất! Làm thế nào tôi có thể kiểm tra hai hoặc nhiều lớp để được loại bỏ? ví dụ sport-, nav-color-?
lowTechsun

Làm thế nào bạn sẽ làm điều này để phù hợp với một lớp kết thúc như thế *-colornào?
Vòng tròn B

3
@lowtechsun bạn có thể thêm vào regex của bạn như thế này (color-|sport-|nav-). Nó sẽ phù hợp color-, hoặc sport-, hoặc nav-. Vì vậy, câu trả lời ở trên sẽ trở thành /(^|\s)(color-|sport-|nav-)\S+/g.
Bogie

1
Câu trả lời được chấp nhận là chính xác, nhưng về mặt thành ngữ, tôi sẽ sử dụng \ b khớp với bất kỳ ranh giới từ nào hơn là nhiều từ hơn (^ | \ s). Vì vậy, ví dụ, để loại bỏ tất cả các lớp bao gồm từ ma thuật theo sau là một số nguyên không âm và chỉ những số đó, tôi khớp với / \ bmagic \ d + \ b /.
CarlEdman

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

5
Tôi thích điều này vì nó làm giảm chi phí và đi thẳng vào vấn đề. Tại sao sử dụng loại bỏ lớp khi attr làm công việc tốt hơn?
Angry Dan

2
tôi nghĩ bạn cần bảo vệ chống lại các lớp trống ( c is undefined)? Ít nhất là khi tôi đã thử nó dưới đây trong plugin của mình trên trang này, $('a').stripClass('post', 1)đã ném "TypeError: Phương thức gọi không thể 'thay thế' của không xác định"
drzaus

1
@Kobi vâng tôi không nghĩ có thể lọc thuộc tính và trả về kết quả không có nó - $('div[class]')chỉ nên trả về các phần tử với class, cho dù chúng có giá trị hay không. kịch bản thử nghiệm: jsfiddle.net/drzaus/m83mv
drzaus

1
@Kobi - Tôi nghĩ rằng tôi thấy những gì bạn đang nhận được; trong các trường hợp cạnh như .removeProp('class')hoặc .className=undefinedbộ lọc [class]vẫn trả về một cái gì đó, chúng chỉ là undefined. Vì vậy, về mặt kỹ thuật, nó vẫn có một lớp (trái ngược với .removeAttr('class'), đó là lý do tại sao nó phá vỡ chức năng của bạn nhưng không phải là biến thể của tôi. Jsfiddle.net/drzaus/m83mv/4
drzaus

1
Thêm một bài kiểm tra nhanh làm việc cho tôi:return c && c.replace(/\bcolor-\S+/g, '');
ssmith

50

Tôi đã viết một plugin có chức năng này được gọi là notifyClass - Loại bỏ các lớp phần tử có khớp ký tự đại diện. Tùy chọn thêm các lớp: https://gist.github.com/1517285

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

1
Thực sự rất tốt ... đã giúp tôi sử dụng lại một số mã mà tôi chỉ cần xóa Twitter Boostrapcác lớp như thế này:$(".search div").children('div').alterClass('span* row-fluid');
Leniel Maccaferri

15

Tôi đã khái quát điều này thành một plugin Jquery, lấy một biểu thức chính quy làm đối số.

Cà phê:

$.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(' ');
  });
};

Vì vậy, trong trường hợp này, việc sử dụng sẽ là (cả Cà phê và Javascript):

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

Lưu ý rằng tôi đang sử dụng Array.filterchức năng không tồn tại trong IE <9. Bạn có thể sử dụng chức năng lọc của Underscore thay thế hoặc Google cho một polyfill như WTFPL này .


11

Nếu bạn muốn sử dụng nó ở những nơi khác, tôi khuyên bạn nên mở rộng. Điều này là làm việc tốt cho tôi.

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

Sử dụng:

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

4

chúng ta có thể nhận được tất cả các lớp bằng .attr("class"), và đến Array, và vòng lặp & bộ lọc:

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

bản demo: http://jsfiddle.net/L2A27/1/


Đã thêm var prefix='color';và thay đổi ...if (classArr[i].substr(0, prefix.length) != prefix)
Rich C

4

Tương tự như câu trả lời của @ tremby , đây là câu trả lời của @ Kobi là một plugin sẽ khớp với tiền tố hoặc hậu tố.

  • ex) dải btn-minibtn-dangerkhông btnkhi stripClass("btn-").
  • ví dụ) dải horsebtncowbtnnhưng không btn-minihoặc btnkhistripClass('btn', 1)

Mã số:

$.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
Đối với hồ sơ, tôi không đồng ý rằng điều này đơn giản hơn.
run

@tremby xin lỗi, tôi có nghĩa là đơn giản hơn trong cách sử dụng thông thường (ví dụ: tiền tố và hậu tố), vì bạn không phải viết regex mỗi lần
drzaus

3
Tôi vẫn không đồng ý. Với phương pháp của bạn, bạn phải đọc tài liệu và nhớ chính xác giá trị endOrBegincần phải là gì. Nó không tự giải thích. Có gì khó khi viết regex? /^match-at-start//match-at-end$/được mọi nhà phát triển JS biết đến. Nhưng mỗi người để riêng mình.
run

1
@tremby khác hơn regexes xin được lạm dụng, một lựa chọn không phù hợp với regex chặt chẽ hơn chữ ký hiện có của addClass, removeClasstoggleClass, được biết đến cho mọi nhà phát triển jQuery. Có gì khó khi đọc tài liệu? ;)
drzaus

2
Không có gì khó khăn khi đọc tài liệu, nhưng như @tremby nói, giải pháp của anh ta là tự giải thích, trong khi của bạn yêu cầu tài liệu. Các giải pháp tự giải thích là đơn giản hơn để sử dụng theo định nghĩa.
Francisco Hodge

2

Đối với một plugin jQuery hãy thử điều này

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

hoặc cái này

$.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

Dựa trên câu trả lời của ARS81 (chỉ khớp với tên lớp bắt đầu bằng), đây là phiên bản linh hoạt hơn. Vừa làhasClass() phiên bản regex.

Sử dụng: $('.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

Điều này sẽ loại bỏ hiệu quả tất cả các tên lớp bắt đầu bằng thuộc tính prefixcủa một nút class. Các câu trả lời khác không hỗ trợ các yếu tố SVG (khi viết bài này), nhưng giải pháp này thực hiện:

$.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, ''));
    });
};

Sẽ không hiệu quả hơn khi tạo RegExpđối tượng một lần, trong số mỗi cuộc gọi lại?
Emile Bergeron

1
@EmileBergeron - đúng vậy! Tôi sẽ thực hiện thay đổi
vsync

2

Tôi đã có cùng một vấn đề và đã đưa ra những điều sau đây sử dụng phương thức _.filter của gạch dưới. Khi tôi phát hiện ra rằng removeClass có một hàm và cung cấp cho bạn một danh sách các tên lớp, thật dễ dàng để biến nó thành một mảng và lọc tên lớp để quay lại phương thức 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
Bạn có thể giải thích những gì dấu gạch chân không trong _.filter
bart

2

Bạn cũng có thể làm điều này với JavaScript vanilla bằng Element . ClassList . Không cần sử dụng biểu thức chính quy:

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

Lưu ý: Lưu ý rằng chúng tôi tạo một Arraybản sao của classListtrước khi bắt đầu, đó là điều quan trọng vì đây classListlà bản phát DomTokenListhành sẽ cập nhật khi các lớp bị xóa.


1

Bạn cũng có thể sử dụng thuộc classNametính của đối tượng DOM của phần tử:

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

1

Một hàm chung loại bỏ bất kỳ lớp nào bắt đầu bằng 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

Một regex tách trên ranh giới từ \bkhông phải là giải pháp tốt nhất cho việc này:

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

hoặc như một mixin jQuery:

$.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

nếu bạn có nhiều hơn một thành phần có tên lớp 'ví dụ', để xóa các lớp 'màu - trong tất cả chúng, bạn có thể thực hiện việc này: [bằng cách sử dụng jquery]

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

nếu bạn không đặt [a-z1-9 -] * trong regex của mình, nó sẽ không xóa các lớp có số hoặc một số '-' trong tên của chúng.


0

Nếu bạn chỉ cần loại bỏ màu thiết lập cuối cùng, những điều sau đây có thể phù hợp với bạn.

Trong tình huống của tôi, tôi cần thêm một lớp màu vào thẻ body trên một sự kiện nhấp chuột và xóa màu cuối cùng được đặt. Trong trường hợp đó, bạn lưu trữ màu hiện tại, rồi tìm thẻ dữ liệu để xóa màu đã đặt cuối cùng.

Mã số:

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

Có thể không chính xác những gì bạn cần, nhưng đối với tôi nó là và đây là câu hỏi SO đầu tiên tôi nhìn vào, vì vậy tôi nghĩ rằng tôi sẽ chia sẻ giải pháp của mình trong trường hợp nó giúp được bất cứ ai.


Điều đó không liên quan ở đây. Bạn có thể đã trả lời câu hỏi của riêng bạn vì đó là một hành vi được khuyến khích trên SO.
Emile Bergeron

@Emile: Đó là sự thật. Tôi có thể làm điều đó vì nó không trả lời trực tiếp câu hỏi ban đầu. Tôi nên để câu trả lời này lên hoặc loại bỏ nó?
redfox05

Vào thời điểm đó, đó là nguy cơ của riêng bạn, nó đã không được bình chọn cũng như không được đánh giá cao. Vì vậy, bạn có thể di chuyển nó đến câu hỏi của riêng bạn mà không có rủi ro. Ngoài ra, hãy cố gắng tránh trùng lặp bằng cách kiểm tra nếu đã có câu hỏi về điều này.
Emile Bergeron

0

Một cách khác để tiếp cận vấn đề này là sử dụng các thuộc tính dữ liệu, về bản chất là duy nhất.

Bạn sẽ đặt màu của một yếu tố như: $el.attr('data-color', 'red');

Và bạn sẽ tạo kiểu cho nó trong css như: [data-color="red"]{ color: tomato; }

Điều này phủ nhận nhu cầu sử dụng các lớp, có tác dụng phụ là cần phải loại bỏ các lớp cũ.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.