PDA

View Full Version : TreeField



mofo
21 May 2009, 11:23 AM
Hi, here is the code if anyone needs a TreeField.
TreeFiel is a "Combobox" compente but instead of open just the items, open a Tree to select any node.
I did this componente thinking at my problems, so if you need to use it maybe you need to do some modification.

All can use it as you want, and if someone wants to do a any improvement, just post here.




Ext.form.TreeField = function(config) {
Ext.form.TreeField.superclass.constructor.call(this, config);
this.addEvents({ 'expand': true, 'collapse': true, 'beforeselect': true, 'select': true, 'beforequery': true });
};
Ext.extend(Ext.form.TreeField, Ext.form.TriggerField, {
defaultAutoCreate: { tag: "input", type: "text", size: "24", autocomplete: "off" },
listWidth: undefined,
listHeight: 100,
listClass: '',
xtype: 'treefield',
triggerClass: 'x-form-arrow-trigger',
shadow: 'sides',
listAlign: 'tl-bl?',
maxHeight: 300,
triggerAction: 'query',
minChars: 4,
queryDelay: 500,
selectOnFocus: false,
queryParam: 'query',
loadingText: 'Loading...',
resizable: false,
handleHeight: 8,
allQuery: '',
mode: 'remote',
minListWidth: 70,
typeAheadDelay: 250,
valueNotFoundText: undefined,
root: undefined,
animate: true,
loader: undefined,
onRender: function(ct, position) {
Ext.form.TreeField.superclass.onRender.call(this, ct, position);

if (Ext.isGecko)
this.el.dom.setAttribute('autocomplete', 'off');

var cls = 'x-combo-list';
this.list = new Ext.Layer({ shadow: this.shadow, cls: [cls, this.listClass].join(' '), constrain: false, containerScroll: true });

var lw = this.listWidth || Math.max(this.wrap.getWidth(), this.minListWidth);
this.list.setWidth(lw);
this.list.swallowEvent('mousewheel');
this.assetHeight = 0;

this.innerList = this.list.createChild({ cls: cls + '-inner' });
this.innerList.setWidth(lw - this.list.getFrameWidth('lr'));
this.innerList.setHeight(this.listHeight);
this.loader = new Ext.tree.TreeLoader({ preloadChildren: true });
this.tree = new Ext.tree.TreePanel({ border: false, root: this.root, animate: this.animate === false, enableDD: false, containerScroll: true, rootVisible: false, renderTo: this.innerList, loader: this.loader });
this.tree.on('click', this.onTreeClick, this);
this.expand(true);
if (this.selectedValue) {
var tn = this.findNode(this.selectedValue);
this.setValue(tn);
this.selectedValue = undefined;
}
this.tree.getSelectionModel().on("selectionchange", this.selectIntoView, this);
this.el.dom.setAttribute('readOnly', true);
this.el.on('mousedown', this.onTriggerClick, this);
this.el.addClass('x-combo-noedit');
},
getSelectedNode: function() { return this.tree.getSelectionModel().getSelectedNode(); },
initValue: function() { },
initEvents: function() {
Ext.form.TreeField.superclass.initEvents.call(this);
this.keyNav = new Ext.KeyNav(this.el, {
"up": function(e) { this.selectPrev(); },
"down": function(e) { if (this.getSelectedNode() == null) this.tree.getRootNode().firstChild.select(); else if (!this.isExpanded()) this.onTriggerClick(); else { this.selectNext(); } },
"left": function(e) { if (this.getSelectedNode() != null) if (this.getSelectedNode().isExpanded()) this.getSelectedNode().collapse(); else if (this.getSelectedNode().parentNode.attributes.id != "$" && this.getSelectedNode().parentNode != null) this.getSelectedNode().parentNode.select(); else this.selectPrev(); },
"right": function(e) { if (this.getSelectedNode() != null) { if (this.getSelectedNode().childNodes.length > 0 && !this.getSelectedNode().isExpanded()) this.getSelectedNode().expand(); else if (this.getSelectedNode().parentNode.lastChild.attributes.id != this.getSelectedNode().attributes.id || this.getSelectedNode().childNodes.length > 0) this.selectNext(); } },
"enter": function(e) { if (this.getSelectedNode() == null) return false; this.onTreeClick(this.getSelectedNode(), e); },
"esc": function(e) { this.collapse(); },
"tab": function(e) { if (this.getSelectedNode() == null) return false; this.onTreeClick(this.getSelectedNode(), e); return true; },
scope: this,
doRelay: function(foo, bar, hname) {
if (hname == 'down' || this.scope.isExpanded())
return Ext.KeyNav.prototype.doRelay.apply(this, arguments);
return true;
},
forceKeyDown: true
});
this.keyNavTree = this.keyNav = new Ext.KeyNav(this.tree.el, {
"enter": function(e) { this.onTreeClick(this.getSelectedNode(), e); },
"esc": function(e) { this.collapse(); },
"tab": function(e) { this.onViewClick(this.getSelectedNode(), e); return true; },
scope: this
});
this.on('blur', this.doForce, this);

},
onDestroy: function() {
if (this.tree) {
if (!this.tree.root.childNodes)
this.tree.root.childNodes = [];
this.tree.destroy();
}
if (this.list)
this.list.destroy();
Ext.form.TreeField.superclass.onDestroy.call(this);
},
fireKey: function(e) {
if (e.isNavKeyPress() && !this.list.isVisible()) {
this.fireEvent("specialkey", this, e);
}
},
onResize: function(w, h) {
Ext.form.TreeField.superclass.onResize.apply(this, arguments);
if (this.list && this.listWidth === undefined) {
var lw = Math.max(w, this.minListWidth);
this.list.setWidth(lw);
this.innerList.setWidth(lw - this.list.getFrameWidth('lr'));
}
},
onSelect: function(tn) {
if (this.fireEvent('beforeselect', this, tn) !== false) {
this.setValue(tn);
this.collapse();
this.fireEvent('select', this, tn);
}
},
getSelectedValue: function() {
return !this.value ? '' : this.value;
},
clearValue: function() {
this.setRawValue('');
this.lastSelectionText = '';
this.applyEmptyText();
this.value = null;
this.selectedNode = null;
},
setValue: function(tn) {
if (!tn) {
tn = {};
this.selectedNode = undefined;
}
else
this.selectedNode = tn;

Ext.form.TreeField.superclass.setValue.call(this, tn.text);
this.lastSelectionText = tn.text;
this.value = tn.attributes.value;
},
findNode: function(value, nodes) {
if (!nodes)
nodes = this.root.childNodes;
if (nodes.length == 0)
return false;

for (var x = 0; x < nodes.length; x++)
if (nodes[x].attributes.value == value)
return nodes[x];
else {
var node = this.findNode(value, nodes[x].childNodes);
if (node)
return node;
}
return false;
},
onTreeClick: function(tn, e) {
this.onSelect(tn);
if (tn)
this.el.focus();
},
restrictHeight: function() {
this.innerList.dom.style.height = '';
var inner = this.innerList.dom;
var h = Math.max(inner.clientHeight, inner.offsetHeight, inner.scrollHeight);
this.innerList.setHeight(h < this.maxHeight ? 'auto' : this.maxHeight);
this.list.beginUpdate();
this.list.setHeight(this.innerList.getHeight() + this.list.getFrameWidth('tb') + (this.resizable ? this.handleHeight : 0) + this.assetHeight);
this.list.alignTo(this.el, this.listAlign);
this.list.endUpdate();
},
onEmptyResults: function() {
this.collapse();
},
isExpanded: function() {
return this.list.isVisible();
},
selectByValue: function(v, scrollIntoView) {
if (v !== undefined && v !== null) {
var tn = this.findNode(v);
if (tn)
this.selectIntoView(null, tn)
}
return false;
},
selectIntoView: function(model, tn) {
if (tn)
this.innerList.scrollChildIntoView(tn.ui.anchor, false);
},
selectNext: function() {
this.tree.getSelectionModel().selectNext();
},
selectPrev: function() {
this.tree.getSelectionModel().selectPrevious();
},
validateBlur: function() {
return !this.list || !this.list.isVisible();
},
doForce: function() {
if (this.el.dom.value.length > 0) {
this.el.dom.value =
this.lastSelectionText === undefined ? '' : this.lastSelectionText;
this.applyEmptyText();
}
},
collapse: function() {
if (!this.isExpanded())
return;

this.list.hide();
Ext.get(document).un('mousedown', this.collapseIf, this);
Ext.get(document).un('mousewheel', this.collapseIf, this);
this.fireEvent('collapse', this);
},
collapseIf: function(e) {
if (!e.within(this.wrap) && !e.within(this.list))
this.collapse();
},
expand: function() {
if (this.isExpanded() || !this.hasFocus)
return;

if (this.selectedNode)
this.tree.selectPath(this.selectedNode.getPath());
else
this.tree.getSelectionModel().clearSelections();
this.list.alignTo(this.el, this.listAlign);
this.list.show();
Ext.get(document).on('mousedown', this.collapseIf, this);
Ext.get(document).on('mousewheel', this.collapseIf, this);
this.fireEvent('expand', this);
},
onTriggerClick: function() {
if (this.disabled)
return;

this.el.focus();
if (this.isExpanded())
this.collapse();
else {
this.hasFocus = true;
this.expand();
}
}
});
Ext.reg("treefield", Ext.form.TreeField);


Thanks.