Birgün gelirde sizinde benim gibi treeview ihtiyacınız olursa işte kodlar takıldığınız yerde ayrıca yardımcı olmaya çalışırım :)

Bağımlılıklar : jQuery & Font Awesome

Kullanımı(dtoList öğeleri INode interface den türetilmesi lazım)

<me:treeView id="testTree" value="#{TreeSampleAction.selectedDtoList}">

<f:selectItems value="#{TreeSampleAction.dtoList}" />

</me:treeView>

Öncelikle Control Class


package tr.com.mypackage.component.tree;

import java.io.ByteArrayInputStream;
import java.io.ObjectInputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.el.ValueExpression;
import javax.faces.component.UIComponent;
import javax.faces.component.UIInput;
import javax.faces.component.UISelectItems;
import javax.faces.context.FacesContext;
import javax.faces.convert.ConverterException;

import org.apache.axis.encoding.Base64;

import tr.com.mypackage.component.tree.INode;

public class MeTreeView extends UIInput implements javax.faces.component.EditableValueHolder {

public static final String TREEVIEW_PREFIX = "inputFile";
private static final String OPTIMIZED_PACKAGE = "tr.com.mypackage.component.";

public String getComponentType() {
return "tr.com.mypackage.faces.tree";
}

public String getRendererType() {
return "tr.com.mypackage.faces.tree";
}

public String getFamily() {
return "tr.com.mypackage.faces.tree";
}

private String styleClass;
private String style;
private Boolean multipleSelect = false;
private java.lang.String onchange;

private List<INode> parentNode;

public String getStyleClass() {
return styleClass + " treeview";
}

public void setStyleClass(String styleClass) {
this.styleClass = styleClass;
}

public String getStyle() {
return style;
}

public void setStyle(String style) {
this.style = style;
}

public Boolean getMultipleSelect() {
return multipleSelect;
}

public void setMultipleSelect(Boolean multipleSelect) {
this.multipleSelect = multipleSelect;
}


public java.lang.String getOnchange() {
if (null != this.onchange) {
return this.onchange;
}
ValueExpression _ve = getValueExpression("onchange");
if (_ve != null) {
return (java.lang.String) _ve.getValue(getFacesContext().getELContext());
} else {
return null;
}
}

public void setOnchange(java.lang.String onchange) {
this.onchange = onchange;
handleAttribute("onchange", onchange);
}

public List<INode> getParentNode() {
return parentNode;
}

public void setParentNode(List<INode> parentNode) {
this.parentNode = parentNode;
}

@SuppressWarnings("unchecked")
public List<MeTreeNode> getNode() throws Exception {
List<MeTreeNode> resultNode = new ArrayList<MeTreeNode>();
Iterator<UIComponent> children = this.getChildren().iterator();
while (children.hasNext()) {
UIComponent child = (UIComponent) children.next();
if (child instanceof UISelectItems) {
Object childValue = ((UISelectItems) child).getValue();
if (childValue instanceof Collection) {
List<INode> nodeList = (List<INode>)childValue;
for (INode node : nodeList) {
if (node.getParent() == null) {
resultNode.add(getChildrenNode(nodeList, node));
}
}
} else {
throw new Exception(
"Tree SelectItems degeri Collection Türünden Olmalı");
}
} else {
throw new Exception("Tree SelectItem objesi kullanılmalıdır");
}
}
return resultNode;
}

public Object saveState(FacesContext context) {
Object values[] = new Object[2];
values[0] = super.saveState(context);
values[1] = parentNode;
values[2] = styleClass;
values[3] = style;
return ((Object) (values));
}

@SuppressWarnings("unchecked")
public void restoreState(FacesContext context, Object state) {
Object values[] = (Object[]) state;
super.restoreState(context, values[0]);
parentNode = (List<INode>) values[1];
styleClass = (String) values[2];
style = (String) values[3];
}

public void validate(FacesContext context) {

List<INode> nodeList = new ArrayList<INode>();
if (context == null) {
throw new NullPointerException();
}
Map<String, String> req = context.getExternalContext().getRequestParameterMap();
for(String check:req.keySet()){
if(check.startsWith(this.getClientId(context)+":"))
nodeList.add((INode)getAsObject(req.get(check)));
}
setValue(nodeList);
}

private MeTreeNode getChildrenNode(List<INode> nodeList, INode node) {
MeTreeNode treeNode = new MeTreeNode(node);
for (INode item : nodeList) {
if (item.getParent() != null && item.getParent().getValue().equals(node.getValue())) {
if (treeNode.getChildren() == null) {
treeNode.setChildren(new ArrayList<MeTreeNode>());
}
MeTreeNode childNode = getChildrenNode(nodeList, item);
treeNode.getChildren().add(childNode);
}
}
return treeNode;
}

private Object getAsObject(String value) {
Object obj = null;

try {
String serializedObj = value;

byte[] byteObj = Base64.decode(serializedObj);
ObjectInputStream ois = new ObjectInputStream(
new ByteArrayInputStream(byteObj));
obj = ois.readObject();
ois.close();
} catch (Exception e) {
throw new ConverterException(
"Transient object cannot be read from stream");
}

return obj;
}

@SuppressWarnings("unchecked")
private void handleAttribute(String name, Object value) {
List<String> setAttributes = null;
String cname = this.getClass().getName();
if (cname != null && cname.startsWith(OPTIMIZED_PACKAGE)) {
setAttributes = (List<String>) this.getAttributes().get("javax.faces.component.UIComponentBase.attributesThatAreSet");
if (setAttributes == null) {
setAttributes = new ArrayList<String>(6);
this.getAttributes().put("javax.faces.component.UIComponentBase.attributesThatAreSet", setAttributes);
}
if (value == null) {
setAttributes.remove(name);
} else if (!setAttributes.contains(name)) {
setAttributes.add(name);
}
}
}

}

Sonra Render Class


package tr.com.mypackage.component.tree;

import java.io.IOException;

import java.util.Collection;

import java.util.Iterator;

import java.util.List;


import javax.faces.component.UIComponent;

import javax.faces.context.FacesContext;

import javax.faces.context.ResponseWriter;

import javax.faces.render.Renderer;


import tr.com.mypackage.component.tree.INode;


public class MeTreeRender extends Renderer {




@SuppressWarnings("rawtypes")

private void writerTreeChild(ResponseWriter writer, MeTreeView treeView,

MeTreeNode node, String name) throws IOException {

String clickScript = "var itemContainer = this.parentElement; if(itemContainer.parentElement.classList.contains('single')==false && itemContainer.parentElement.classList.contains('close')) {itemContainer.parentElement.classList.remove('close');itemContainer.parentElement.classList.add('open'); }else{itemContainer.parentElement.classList.remove('open');itemContainer.parentElement.classList.add('close');}";

writer.startElement("li", treeView);

writer.startElement("div", treeView);

writer.writeAttribute("class", "tree-item", null);

writer.startElement("i", treeView);

writer.writeAttribute("class", "tree-icon", null);

writer.writeAttribute("onclick", "javascript:" + clickScript, null);

writer.endElement("i");

String checkType = "radio";

if (treeView.getMultipleSelect() == true) {

checkType = "checkbox";

}

writer.startElement("input", treeView);

writer.writeAttribute("type", checkType, null);

writer.writeAttribute("onchange", "javascript:treeChangeState(this);", null);

// writer.writeAttribute("style", "display:none", null);

writer.writeAttribute("name", name + ":" + node.getValue(), null);

writer.writeAttribute("value", node.getAsString(), null);

if (treeView.getValue() != null) {

if (treeView.getValue() instanceof INode) {

if (((INode) treeView.getValue()).getValue().equals(

node.getValue())) {

writer.writeAttribute("checked", true, null);

}

}

if (treeView.getValue() instanceof Collection) {

Iterator valueList = ((Collection) treeView.getValue())

.iterator();

while (valueList.hasNext()) {

INode nodeValue = ((INode) valueList.next());

if (nodeValue.getValue().equals(node.getValue())) {

writer.writeAttribute("checked", true, null);

break;

}

}

}

}

writer.endElement("input");

writer.writeAttribute("class", "tree-item", null);

writer.startElement("label", treeView);

writer.writeAttribute("id", name + ":" + node.getValue(), null);

writer.writeAttribute("onclick", "javascript:" + clickScript, null);

writer.write(node.getLabel());

writer.endElement("label");

writer.endElement("div");

if (node.getChildren() != null && node.getChildren().size() > 0) {

writer.writeAttribute("class", " close", null);

writer.startElement("ul", treeView);

for (MeTreeNode item : node.getChildren()) {

writerTreeChild(writer, treeView, item, name);

}

writer.endElement("ul");

} else {

writer.writeAttribute("class", " single", null);

}

writer.endElement("li");

}




public void encodeBegin(FacesContext context, UIComponent component)

throws IOException {

String id = component.getClientId(context);

MeTreeView treeView = (MeTreeView) component;

/*

* UIComponent hidden = createHiddenField(id);

* c.getParent().getChildren().add(hidden);

*/

ResponseWriter writer = context.getResponseWriter();




writer.startElement("div", treeView);

writer.writeAttribute("id", id + "Container", null);

writer.writeAttribute("class", treeView.getStyleClass(), null);

writer.writeAttribute("style", treeView.getStyle(), null);

writer.startElement("ul", treeView);

List<MeTreeNode> nodeList = null;

try {

nodeList = treeView.getNode();

} catch (Exception e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

for (MeTreeNode node : nodeList) {

if (node != null) {

writerTreeChild(writer, treeView, node, id);

}

}

writer.endElement("ul");

writer.endElement("div");

}




public void decode(FacesContext facesContext, UIComponent uiComponent) {

super.decode(facesContext, uiComponent);

}




}


INode Interface class



package tr.com.mypackage.component.tree;
import java.io.Serializable;
public interface INode extends Serializable {


public INode getParent();


public Object getValue();


public String getLabel();


}


Javascript


var treeChangeState = function(e) {

var checked = jQuery(e).prop("checked"),

container = jQuery(e).parent().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 = (jQuery(this).children('.tree-item').children('input[type="checkbox"]').prop("checked") === checked);

});



if (all && checked) {

parent.children('.tree-item').children('input[type="checkbox"]').prop({

indeterminate: false,

checked: checked

});

checkSiblings(parent);

} else if (all && !checked) {

parent.children('.tree-item').children('input[type="checkbox"]').prop("checked", checked);

parent.children('.tree-item').children('input[type="checkbox"]').prop("indeterminate", (parent.find('input[type="checkbox"]:checked').length > 0));

checkSiblings(parent);

} else {

el.parents("li").children('.tree-item').children('input[type="checkbox"]').prop({

indeterminate: true,

checked: false

});

}

}



checkSiblings(container);

}

ve Son Olarak Css dosyası


.treeview {

width: 100%;

overflow: hidden;

overflow-y: auto;

max-height: 20em;

border: 1px solid #ccc;

}




.treeview .close, .treeview .open {

font-size: inherit;

opacity: 1;

font-weight: 700;

line-height: 1;

text-shadow: none;

float: none;

}




.treeview ul {

list-style: none;

list-style-type: none;

padding: 0px;

margin: 0px;

display: block;

}




.treeview ul ul {

margin: 2em 0em 0em 1.2em;

}

.treeview li.close>ul{

display:none;

}

.treeview ul li {

display: table;

width: 100%;

margin: .5em 0em 0em 0em;

position: relative;

padding: 0px 0px 0px 1em;

}




.treeview input {

display: block;

float: left;

margin: .3em;

}




.treeview i {

float: left;

display: inline-block;

font-family: FontAwesome;

font-style: normal;

font-weight: normal;

line-height: 1;

-webkit-font-smoothing: antialiased;

-moz-osx-font-smoothing: grayscale;

color: #959595;

font-size: 1.26em;

margin: .23em .1em .1em 1px;

}




.treeview li.close>.tree-item>i:before {

content: "\f196";

}




.treeview li.open>.tree-item>i:before {

content: "\f147";

}




.treeview li.single>.tree-item>i:before {

content: "\f0c8";

cursor: default;

}

.treeview .tree-item {

border: 1px solid transparent;

cursor: pointer;

padding: 0px;

float: left;

z-index:10;

}

.treeview .tree-item label{

cursor: pointer;

font-weight: normal;

margin: .3em 0em;

}

.treeview .tree-item:hover label{

color: #0B6ED1;

}