Как удалить класс CSS из компонента Wicket?

Довольно просто динамически добавить класс CSS к компоненту в Java-коде с помощью AttributeAppender:

component.add(new AttributeAppender("class", true, new Model<String>("foo"), " "));

Или, если вы извлекли это в соответствующий метод или класс утилиты, просто что-то вроде:

component.add(WicketUtils.cssClassAppender("foo"));

Но как я могу удалить класс CSS?

Вы можете легко удалить все классы CSS, полностью очистив атрибут класса:

component.add(new SimpleAttributeModifier("class", ""));

... но это неприемлемо, если у компонента есть другие классы CSS, которые вы не хотите удалять.

Wicket 1.4 (но не стесняйтесь публиковать советы, относящиеся к более поздним версиям).

Ответы

Ответ 1

Вот один из способов, которым я придумал:

public class CssClassRemover extends AttributeModifier {
    public CssClassRemover(String cssClass) {
        super("class", false, new Model<String>(cssClass));
    }

    @Override
    protected String newValue(String currentValue, String valueToRemove) {
        // NB: naive approach; breaks with e.g. "foo foo-bar" & "foo"
        return currentValue.replaceAll(valueToRemove, "");
    }
}

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

component.add(new CssClassRemover("foo"))

(Разумеется, вы также можете просто создавать анонимные подклассы AttributeModifier по мере необходимости, но поместить логику в отдельный класс или метод утилиты очень много очищает.)

Изменить: улучшенная версия newValue(), которая лучше обрабатывает угловые случаи (см. комментарий by biziclop). NB: использует Guava. (Вы можете публиковать более простые версии (regex?).)

@Override
protected String newValue(String currentValue, String valueToRemove) {
    if (currentValue == null) return "";

    Set<String> classes = Sets.newHashSet(Splitter.on(" ").split(currentValue));
    classes.remove(valueToRemove);
    return Joiner.on(" ").join(classes); 
}

Ответ 2

Основываясь на Jonik answer, следующее добавляет отрицательный lookahead, чтобы игнорировать вхождения в середине другого класса стиля (и нечувствителен к регистру).

public class StyleClassRemover extends AttributeModifier {

    public StyleClassRemover(final String cssClass) {
        super("class", false, Model.of(cssClass));
    }

    @Override
    protected String newValue(final String currentValue, final String valueToRemove) {
        if (currentValue == null) {
            return "";
        }

        final String patternString = "(^|\\s+)" + Pattern.quote(valueToRemove) + "(?!\\S)";
        return Pattern.compile(patternString, Pattern.CASE_INSENSITIVE).matcher(currentValue).replaceAll("");
    }
}

Протестированный ввод: http://fiddle.re/ah0ca6

Ответ 3

У Wicket 1.5+ есть org.apache.wicket.AttributeModifier # remove()