This is modified version of original j.bruni version.
Things changed:
1.It is possible now to load tree content from JSON and mark node as 'checked':true. Be sure to pass boolean value not the string, otherwise checkbox will remain unchecked! Remarking partial node status is done by script, so there is no need to send info about partial status!
2. Changed css, to show correctly in Webkit browsers.
3. Resolved issue with not preloaded children nodes.
4. Comment: specify only
Code:
uiProviders: {tristate: Ext.tree.TreeNodeTriStateUI }
, as UI provider!
Tested against 3.2.2 (but should be okay with 3.2.x). FF3.6.3, Opera 10.54, Safari 5.
CSS:
Code:
.styledCheckbox {
height: 13px;
width: 13px;
filter: alpha(opacity=0.0);
opacity: 0.0;
outline: 0;
}
.styledCheckboxWrap {
position: relative;
background: url('checkboxes.gif') no-repeat top left;
width: 13px;
height: 13px;
margin: 3px;
}
.ext-webkit .styledCheckboxWrap {
padding-bottom:1px;
}
.wrapChecked{ background-position: 0px -13px; }
.wrapPartial{ background-position: 0px -26px; }
TreeNodeTriStateUI.js
Code:
Ext.tree.TreeNodeTriStateUI = function() {
Ext.tree.TreeNodeTriStateUI.superclass.constructor.apply(this, arguments);
this.partial = false;
};
Ext.extend(Ext.tree.TreeNodeTriStateUI, Ext.tree.TreeNodeUI, {
renderElements : function(n, a, targetNode, bulkRender){
this.indentMarkup = n.parentNode ? n.parentNode.ui.getChildIndent() : '';
var cb = Ext.isBoolean(a.checked),
nel,
href = a.href ? a.href : Ext.isGecko ? "" : "#",
buf = ['<li class="x-tree-node"><div ext:tree-node-id="',n.id,'" class="x-tree-node-el x-tree-node-leaf x-unselectable ', a.cls,'" unselectable="on">',
'<span class="x-tree-node-indent">',this.indentMarkup,"</span>",
'<img src="', this.emptyIcon, '" class="x-tree-ec-icon x-tree-elbow" />',
'<img src="', a.icon || this.emptyIcon, '" class="x-tree-node-icon',(a.icon ? " x-tree-node-inline-icon" : ""),(a.iconCls ? " "+a.iconCls : ""),'" unselectable="on" />',
cb ? ('<span class="styledCheckboxWrap '+ (a.checked ? ' wrapChecked' :'')+'"><input class="x-tree-node-cb styledCheckbox" type="checkbox" ' +
(a.checked ? 'checked="checked" />' : '/>') + '</span>' ) : '', //modified for load checked nodes feature
'<a hidefocus="on" class="x-tree-node-anchor" href="',href,'" tabIndex="1" ',
a.hrefTarget ? ' target="'+a.hrefTarget+'"' : "", '><span unselectable="on">',n.text,"</span></a></div>",
'<ul class="x-tree-node-ct" style="display:none;"></ul>',
"</li>"].join('');
if(bulkRender !== true && n.nextSibling && (nel = n.nextSibling.ui.getEl())){
this.wrap = Ext.DomHelper.insertHtml("beforeBegin", nel, buf);
}else{
this.wrap = Ext.DomHelper.insertHtml("beforeEnd", targetNode, buf);
}
this.elNode = this.wrap.childNodes[0];
this.ctNode = this.wrap.childNodes[1];
var cs = this.elNode.childNodes;
this.indentNode = cs[0];
this.ecNode = cs[1];
this.iconNode = cs[2];
var index = 3;
if(cb){
this.checkbox = cs[3].firstChild;
// fix for IE6
this.checkbox.defaultChecked = this.checkbox.checked;
index++;
}
this.anchor = cs[index];
this.textNode = cs[index].firstChild;
//updating partial nodes
if (a.checked) n.bubble( function(n){ if (n.parentNode) n.getUI().updateCheck(true) } );//pass in true -> inform, that this is loaded node!
},
toggleCheck: function(value, partial, isLoad){
var cb = this.checkbox;
if(cb){
cb.checked = (value === undefined ? !cb.checked : value);
cb.parentNode.className = 'styledCheckboxWrap' + (cb.checked ? (partial ? ' wrapPartial' : ' wrapChecked') : '');
this.partial = cb.checked && partial;
if(!isLoad) this.onCheckChange();
}
},
updateCheck: function(isLoad){
if ( this.node.childNodes.length == 0 )
return;
this.partial = 0;
Ext.each( this.node.childNodes, function(item){
var ui = item.getUI();
if (ui.isChecked()) {
this.partial++;
if (ui.partial)
{
this.toggleCheck(true,true,isLoad);
return false;
}
}
}, this );
if ( this.partial !== true )
this.toggleCheck( this.partial > 0, this.partial < this.node.childNodes.length, isLoad );
}
});
And in Your code:
Code:
this.myTreeStateTree = new Ext.tree.TreePanel({
height:270,
autoScroll: true,
animate: false,
containerScroll: true,
loader: new Ext.tree.TreeLoader({
directFn: XXX.treeLoadFunction,
paramOrder: ['compid'], //param order
baseParams: { //parameters to send along with tree load
compid : 0 // specify default value
},
uiProviders: {tristate: Ext.tree.TreeNodeTriStateUI }
}),
root: {
nodeType: 'async',
text: 'Node title goes here',
draggable: false,
isTarget:false,
editable :false,
id: 'src',
uiProvider:false,
iconCls:"ico-application-share"
},
listeners:{
scope:this,
checkchange:{
fn:this.checkChange
}
}
});
.
.
.
checkChange:function(node, checked){
if (!this.changing)
{
this.changing = true;
node.expand(true, false,function(node){
if (checked)
node.cascade( function(node){ node.getUI().toggleCheck(true) } );
else
node.cascade( function(node){ node.getUI().toggleCheck(false) } );
node.bubble( function(node){ if (node.parentNode) node.getUI().updateCheck(false) } );
});
this.changing = false;
}
},
.
.