Note The
indeterminate state of a checkbox is visual only.
Checkboxes
can be submitted as checked or unchecked, but visually there are actually three
states a checkbox can be in: checked, unchecked, or indeterminate, as in the
below figure:
The indeterminate
state is useful when we deal with nested checkboxes. Practically, each checkbox
that have children is checked if all of its children are checked, and is indeterminate
("partially" checked) if at least one of its children is unchecked.
Note The
indeterminate state cannot be set via HTML, is not an HTML attribute for it. It
is a property of checkboxes though, which you can change via JavaScript.
The Indeterminate Checkboxes article covers
this topic for pure HTML and JavaScript. The JavaScript presented there is used
next for writing an example of indeterminate checkboxes based on JSF and
OmniFaces Tree component. Since we are talking about a checkboxes hierarchical
structure (see picture above), we can shape it as an OmniFaces Tree as below (a
CheckItem
instance encapsulates a checkbox information):
public class
CheckItem implements Serializable {
private static final long serialVersionUID =
1L;
private String label;
private boolean value;
public CheckItem(String label, boolean value)
{
this.label = label;
this.value = value;
}
// getters and setters
}
And the CheckBean
shapes an hierarchy of CheckItems:
@Named
@SessionScoped
public class
ChecksBean implements Serializable {
private static final long serialVersionUID =
1L;
private TreeModel<CheckItem> tree;
@PostConstruct
public void init() {
tree = new ListTreeModel<>();
tree.addChild(new
CheckItem("Install", false))
.addChild(new CheckItem("Demos",
false))
.getParent().addChild(new
CheckItem("Development", false))
.addChild(new
CheckItem("Simple", false))
.getParent().addChild(new
CheckItem("Advanced", false))
.getParent().getParent().addChild(new
CheckItem("Debug", false))
.getParent().getParent().addChild(new
CheckItem("Repair", false))
.addChild(new
CheckItem("Demos", false))
.getParent().addChild(new
CheckItem("Tools", false))
.getParent().addChild(new
CheckItem("Kit", false));
}
public TreeModel<CheckItem> getTree() {
return
tree;
}
}
Further we
display the hierarchy via a JSF page:
<h:form>
<o:tree
value="#{checksBean.tree}" var="t">
<o:treeNode>
<ul>
<o:treeNodeItem>
<li>
<h:selectBooleanCheckbox
id="checkboxId" value="#{t.value}"/>
<h:outputLabel
for="checkboxId">#{t.label}</h:outputLabel>
<o:treeInsertChildren />
</li>
</o:treeNodeItem>
</ul>
</o:treeNode>
</o:tree>
<h:commandButton
value="Submit">
<f:ajax execute="@form"
render=":panelId"/>
</h:commandButton>
</h:form>
Finally, we
just add the JavaScript code from the IndeterminateCheckboxes article. This is based on jQuery, but you can rewrite it as
plain JavaScript:
$(function
() {
$('input[type="checkbox"]').change(function
(e) {
var checked =
$(this).prop("checked"),
container = $(this).parent(),
siblings = container.siblings();
container.find('input[type="checkbox"]').prop({
indeterminate: false,
checked: checked
});
function checkSiblings(el) {
var parent = el.parent().parent(),
all
= true;
el.siblings().each(function () {
return
all =
($(this).children('input[type="checkbox"]').prop("checked")
=== checked);
});
//<![CDATA[
if
(all && checked) {
//]]>
parent.children('input[type="checkbox"]').prop({
indeterminate:
false,
checked:
checked
});
checkSiblings(parent);
//<![CDATA[
} else if (all && !checked) {
//]]>
parent.children('input[type="checkbox"]').prop("checked",
checked);
parent.children('input[type="checkbox"]').prop("indeterminate",
(parent.find('input[type="checkbox"]:checked').length > 0));
checkSiblings(parent);
} else {
el.parents("li").children('input[type="checkbox"]').prop({
indeterminate: true,
checked: false
});
}
}
checkSiblings(container);
});
});
Just for
testing I have displayed another tree (with ID, panelId) as below:
The complete
source code is available on GitHub.
Niciun comentariu :
Trimiteți un comentariu