Skip to content

Commit

Permalink
Add addClass, removeClass, toggleClass, hasClass to Element and Eleme…
Browse files Browse the repository at this point in the history
…nts.

Closes #2
  • Loading branch information
jhy committed Feb 7, 2010
1 parent a9d69ab commit 87877c9
Show file tree
Hide file tree
Showing 4 changed files with 146 additions and 5 deletions.
65 changes: 63 additions & 2 deletions src/main/java/org/jsoup/nodes/Element.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.jsoup.nodes;

import org.apache.commons.lang.Validate;
import org.apache.commons.lang.StringUtils;
import org.jsoup.parser.Parser;
import org.jsoup.parser.Tag;
import org.jsoup.select.Collector;
Expand Down Expand Up @@ -602,17 +603,29 @@ public String className() {

/**
* Get all of the element's class names. E.g. on element {@code <div class="header gray"}>},
* returns a set of two elements {@code "header", "gray"}.
* returns a set of two elements {@code "header", "gray"}. Note that modifications to this set are not pushed to
* the backing {@code class} attribute; use the {@link #classNames(java.util.Set)} method to persist them.
* @return set of classnames, empty if no class attribute
*/
public Set<String> classNames() {
if (classNames == null) {
String[] names = className().split("\\s+");
classNames = new HashSet<String>(Arrays.asList(names));
classNames = new LinkedHashSet<String>(Arrays.asList(names));
}
return classNames;
}

/**
Set the element's {@code class} attribute to the supplied class names.
@param classNames set of classes
@return this element, for chaining
*/
public Element classNames(Set<String> classNames) {
Validate.notNull(classNames);
attributes.put("class", StringUtils.join(classNames, " "));
return this;
}

/**
* Tests if this element has a class.
* @param className name of class to check for
Expand All @@ -622,6 +635,54 @@ public boolean hasClass(String className) {
return classNames().contains(className);
}

/**
Add a class name to this element's {@code class} attribute.
@param className class name to add
@return this element
*/
public Element addClass(String className) {
Validate.notNull(className);

Set<String> classes = classNames();
classes.add(className);
classNames(classes);

return this;
}

/**
Remove a class name from this element's {@code class} attribute.
@param className class name to remove
@return this element
*/
public Element removeClass(String className) {
Validate.notNull(className);

Set<String> classes = classNames();
classes.remove(className);
classNames(classes);

return this;
}

/**
Toggle a class name on this element's {@code class} attribute: if present, remove it; otherwise add it.
@param className class name to toggle
@return this element
*/
public Element toggleClass(String className) {
Validate.notNull(className);

Set<String> classes = classNames();
if (classes.contains(className))
classes.remove(className);
else
classes.add(className);
classNames(classes);

return this;
}

void outerHtml(StringBuilder accum) {

accum
Expand Down
59 changes: 56 additions & 3 deletions src/main/java/org/jsoup/select/Elements.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,16 @@ public String attr(String attributeKey) {
}

/**
Checks if the first matched value has this attribute set.
Checks if any of the matched elements have this attribute set.
@param attributeKey attribute key
@return true if the first element has the attribute; false if it doesn't, or if no elements were matched.
@return true if any of the elements have the attribute; false if none do.
*/
public boolean hasAttr(String attributeKey) {
return !contents.isEmpty() && first().hasAttr(attributeKey);
for (Element element : contents) {
if (element.hasAttr(attributeKey))
return true;
}
return false;
}

/**
Expand All @@ -73,6 +77,55 @@ public Elements removeAttr(String attributeKey) {
}
return this;
}

/**
Add the class name to every matched element's {@code class} attribute.
@param className class name to add
@return this
*/
public Elements addClass(String className) {
for (Element element : contents) {
element.addClass(className);
}
return this;
}

/**
Remove the class name from every matched element's {@code class} attribute, if present.
@param className class name to remove
@return this
*/
public Elements removeClass(String className) {
for (Element element : contents) {
element.removeClass(className);
}
return this;
}

/**
Toggle the class name on every matched element's {@code class} attribute.
@param className class name to add if missing, or remove if present, from every element.
@return this
*/
public Elements toggleClass(String className) {
for (Element element : contents) {
element.toggleClass(className);
}
return this;
}

/**
Determine if any of the matched elements have this class name set in their {@code class} attribute.
@param className class name to check for
@return true if any do, false if none do
*/
public boolean hasClass(String className) {
for (Element element : contents) {
if (element.hasClass(className))
return true;
}
return false;
}

/**
* Get the combined text of all the matched elements.
Expand Down
13 changes: 13 additions & 0 deletions src/test/java/org/jsoup/nodes/ElementTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,19 @@ public class ElementTest {
assertFalse(doc.hasClass("mellow"));
}

@Test public void testClassUpdates() {
Document doc = Jsoup.parse("<div class='mellow yellow'></div>");
Element div = doc.select("div").first();

div.addClass("green");
assertEquals("mellow yellow green", div.className());
div.removeClass("red"); // noop
div.removeClass("yellow");
assertEquals("mellow green", div.className());
div.toggleClass("green").toggleClass("red");
assertEquals("mellow red", div.className());
}

@Test public void testOuterHtml() {
Document doc = Jsoup.parse("<div title='Tags &amp;c.'><img src=foo.png><p><!-- comment -->Hello<p>there");
assertEquals("<html><head></head><body><div title=\"Tags &amp;c.\"><img src=\"foo.png\" /><p><!-- comment -->Hello</p><p>there</p></div></body></html>",
Expand Down
14 changes: 14 additions & 0 deletions src/test/java/org/jsoup/select/ElementsTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,20 @@ public class ElementsTest {
assertEquals("classy", ps.last().attr("style"));
assertEquals("bar", ps.last().attr("class"));
}

@Test public void classes() {
Document doc = Jsoup.parse("<div><p class='mellow yellow'></p><p class='red green'></p>");

Elements els = doc.select("p");
assertTrue(els.hasClass("red"));
assertFalse(els.hasClass("blue"));
els.addClass("blue");
els.removeClass("yellow");
els.toggleClass("mellow");

assertEquals("blue", els.get(0).className());
assertEquals("red green blue mellow", els.get(1).className());
}

@Test public void text() {
String h = "<div><p>Hello<p>there<p>world</div>";
Expand Down

0 comments on commit 87877c9

Please sign in to comment.