/**
* A Picker field that contains a tree panel on its popup, enabling selection of tree nodes.
*/
Ext.define('Ips.view.strategy.TermTreePicker', {
extend: 'Ext.form.field.Picker',
xtype: 'multitreepicker',
requiers:['Ext.data.TreeStore'],
uses: [
'Ext.tree.Panel'
],
triggerCls: Ext.baseCSSPrefix + 'form-arrow-trigger',
records:new Array(),
values:new Array(),
config: {
rootVisible:false,
/**
* @cfg {Ext.data.TreeStore} store
* A tree store that the tree picker will be bound to
*/
store: null,
/**
* @cfg {String} displayField
* The field inside the model that will be used as the node's text.
* Defaults to the default value of {@link Ext.tree.Panel}'s `displayField` configuration.
*/
displayField: 'text',
/**
* @cfg {Array} columns
* An optional array of columns for multi-column trees
*/
columns: null,
/**
* @cfg {Boolean} selectOnTab
* Whether the Tab key should select the currently highlighted item. Defaults to `true`.
*/
selectOnTab: true,
/**
* @cfg {Number} maxPickerHeight
* The maximum height of the tree dropdown. Defaults to 300.
*/
maxPickerHeight: 300,
/**
* @cfg {Number} minPickerHeight
* The minimum height of the tree dropdown. Defaults to 100.
*/
minPickerHeight: 100,
},
editable: false,
initComponent: function() {
var me = this;
me.callParent(arguments);
me.addEvents(
/**
* @event select
* Fires when a tree node is selected
* @param {Ext.ux.TreePicker} picker This tree picker
* @param {Ext.data.Model} record The selected record
*/
'select'
);
me.mon(me.store, {
scope: me,
load: me.onLoad,
update: me.onUpdate
});
},
/**
* Creates and returns the tree panel to be used as this field's picker.
*/
createPicker: function() {
var me = this,
picker = new Ext.tree.Panel({
rootVisible: me.rootVisible,
useArrows:true,
shrinkWrapDock: 2,
store: me.store,
floating: true,
displayField: me.displayField,
columns: me.columns,
minHeight: me.minPickerHeight,
maxHeight: me.maxPickerHeight,
manageHeight: false,
shadow: false,
listeners: {
scope: me,
itemclick: me.onItemClick,
//checkchange: me.onCheckChange,
//itemexpand: me.onitemExpand,
afteritemexpand: me.AfterItemExpand
},
viewConfig: {
listeners: {
scope: me,
render: me.onViewRender
},
}
}),
view = picker.getView();
//console.log(me.store);
if (Ext.isIE9 && Ext.isStrict) {
// In IE9 strict mode, the tree view grows by the height of the horizontal scroll bar when the items are highlighted or unhighlighted.
// Also when items are collapsed or expanded the height of the view is off. Forcing a repaint fixes the problem.
view.on({
scope: me,
highlightitem: me.repaintPickerView,
unhighlightitem: me.repaintPickerView,
afteritemexpand: me.repaintPickerView,
afteritemcollapse: me.repaintPickerView
});
}
return picker;
},
onViewRender: function(view){
view.getEl().on('keypress', this.onPickerKeypress, this);
},
/**
* repaints the tree view
*/
repaintPickerView: function() {
var style = this.picker.getView().getEl().dom.style;
// can't use Element.repaint because it contains a setTimeout, which results in a flicker effect
style.display = style.display;
},
/**
* Aligns the picker to the input element
*/
alignPicker: function() {
var me = this,
picker;
if (me.isExpanded) {
picker = me.getPicker();
if (me.matchFieldWidth) {
// Auto the height (it will be constrained by max height)
picker.setWidth(me.bodyEl.getWidth());
}
if (picker.isFloating()) {
me.doAlign();
}
}
},
/**
* Handles a click even on a tree node
* @private
* @param {Ext.tree.View} view
* @param {Ext.data.Model} record
* @param {HTMLElement} node
* @param {Number} rowIndex
* @param {Ext.EventObject} e
*/
onItemClick: function(view, record, node, rowIndex, e) {
var checked = record.data.checked? false: true;
this.onCheckChange(record, checked);
//this.selectItem(record);
},
/**
* Handles a checkchange even on a tree node
* @private
* @param {Ext.data.NodeInterface} node
* @param {Boolean} checked
* have a question: why NodeInterface looks just like the Model?
*/
onCheckChange: function(node, checked){//only one level's checked is changed
var me = this;
node.set('checked', checked);
if(checked){//change from unchecked to checked
node.cascadeBy(function(cNode){/*ok~*/
me.removeChildItems(cNode);
if(cNode.hasChildNodes()){
cNode.eachChild(function(childNode){
childNode.set('checked',true);
});
}
});
me.selectItem(node);//this function can refresh the value shown in textfield//
node.bubble(function(pNode){//pNode begins from the current Node/*ok~*/
/*so i directly find it's parent and check if the parent's children
*is all checked(true), if it is then set the parentNode's checked
*'true*/
if(pNode.parentNode != null){
var checkParent = true;
pNode.parentNode.eachChild(function (subling){
if(!subling.data.checked){checkParent = false;}
});
if(checkParent){
pNode.parentNode.set('checked',true);
me.removeChildItems(pNode.parentNode);
me.selectItem(pNode.parentNode);
}
}
});
}else{//change from checked to unchecked
node.bubble(function(pNode){
if(pNode.parentNode != null){
me.addChildItems(pNode.parentNode);//the current node is also added
}
me.removeItem(pNode);//the current node is also removed
pNode.set('checked',false);
});
node.cascadeBy(function(cNode){
cNode.set('checked',false);
});
}
},
onitemExpand: function(node, opts){
var me = this,
picker = me.picker;
//picker.expandPath(node.getPath());
},
AfterItemExpand: function(node, index, item, opts){
//alert('after expand this node');
},
/**
* Handles a keypress event on the picker element
* @private
* @param {Ext.EventObject} e
* @param {HTMLElement} el
*/
onPickerKeypress: function(e, el) {
var key = e.getKey();
if(key === e.ENTER || (key === e.TAB && this.selectOnTab)) {
this.selectItem(this.picker.getSelectionModel().getSelection()[0]);
}
},
/**
* Changes the selection to a given record and closes the picker
* @private
* @param {Ext.data.Model} record
*/
selectItem: function(record) {
var me = this;
//records.push(record.raw.text);
//Ext.Array.each(records, function(rec){
// names.push(rec.raw.text);
//});
me.setValue(record.getId());
//me.picker.hide();
me.inputEl.focus();
me.fireEvent('select', me, record)
},
addChildItems: function(pNode){
var me = this;
if(pNode.data.checked && pNode.hasChildNodes()){//declude the selected Node
pNode.eachChild(function (node){
if(node.data.checked){
me.selectItem(node);
}
});
}
},
removeItem: function(node){
var me = this;
//if(node != null){/*the case that node is null is not exist in current situation*/
var tmpRecord = (node? node.get(me.displayField) : '');
var tmpIndex = me.records.indexOf(tmpRecord);
if( tmpRecord != '' && tmpIndex != -1){
me.records.splice(tmpIndex,1);
}
var tmpValue = node?node.get('id'):'';//this.value.toString();
var tmpValueIndex = me.values.indexOf(tmpValue);
if(tmpValue != '' && tmpValueIndex != -1){
me.values.splice(tmpValueIndex,1);
}
//}
me.setRawValue(me.records ? me.records.toString():'');
},
removeChildItems: function(record){
var me = this;
if(record.hasChildNodes()){
record.eachChild(function (node){
if(node.data.checked){
me.removeItem(node);
}
});
}
},
/**
* Runs when the picker is expanded. Selects the appropriate tree node based on the value of the input element,
* and focuses the picker so that keyboard navigation will work.
* @private
*/
onExpand: function() {
console.log('expand the picker');
var me = this,
picker = me.picker,
store = picker.store,
value = me.value,
node;
if (value) {
node = store.getNodeById(value);
}
if (!node) {
node = store.getRootNode();
}
picker.selectPath(node.getPath());
Ext.defer(function() {
picker.getView().focus();
}, 1);
},
/**
* Sets the specified value into the field
* @param {Mixed} value
* @return {Ext.ux.TreePicker} this
*/
setValue: function(value) {
var me = this,
record;
me.value = value;
if (me.store.loading) {//Ensure it is processed by the onLoad method.
return me;
}
// try to find a record in the store that matches the value
record = value ? me.store.getNodeById(value) : me.store.getRootNode();
if (value === undefined) {
record = me.store.getRootNode();
me.value = record.getId();
} else {
record = me.store.getNodeById(value);
// set the raw value to the record's display field if a record was found
var tmpRecord = (record? record.get(me.displayField) : '');
var tmpIndex = me.records.indexOf(tmpRecord);
if( tmpRecord != '' && tmpIndex == -1){
me.records.push(tmpRecord);
}
var tmpValue = record?record.get('id'):'';//this.value.toString();
var tmpValueIndex = me.values.indexOf(tmpValue);
if(tmpValue!= '' && tmpValueIndex == -1){
me.values.push(tmpValue);
}
//console.log('length:' + me.records.length);
me.setRawValue(me.records ? me.records.toString():'');
}
return me;
},
getSubmitValue: function(){
return this.value;
},
/**
* Returns the current data value of the field (the idProperty of the record)
* @return {Number}
*/
getValue: function() {
return (this.values ? this.values.toString():'');
},
/**
* Handles the store's load event.
* @private
*/
onLoad: function() {
var value = this.value;
if (value) {
this.setValue(value);
}
},
onUpdate: function(store, rec, type, modifiedFieldNames){
var display = this.displayField;
if (type === 'edit' && modifiedFieldNames && Ext.Array.contains(modifiedFieldNames, display) && this.value === rec.getId()) {
this.setRawValue(rec.get(display));
}
}
});
分享到:
相关推荐
在ExtJS4中,多选下拉树(Multi Select Tree)是一种用户界面组件,它结合了下拉菜单和树形结构,允许用户从层级结构中选择多个项目。这个组件在数据管理、分类选择等场景中非常实用。 在实现多选下拉树时,我们...
在ExtJS中,"下拉多选树"(Combobox Tree)是一种结合了下拉框和树形结构的组件,它允许用户在下拉菜单中选择多个树节点,提供了一种高效且直观的用户交互方式。 1. **下拉树组件**:在ExtJS中,树形组件...
在ExtJS中,ComboBox是提供下拉选择功能的基础组件,但默认情况下,ComboBox仅支持单选。要实现多选,我们需要对其进行扩展或利用现有的多选扩展插件。 1. **多选模式**: 在ExtJS中,我们可以通过设置`...
在这个特定的情况下,我们讨论的是一个定制的下拉树菜单控件——ComboBoxTree,它在ExtJS4中实现了单选和多选功能,并且具备展开选中指定节点的能力。这个控件在实际项目中已经被广泛使用并证明了其稳定性和实用性,...
总结起来,"extjs多选 下拉框扩展"是为了满足ExtJS应用中多选功能的需求,通过对原生ComboBox组件进行扩展和定制,实现了带有复选框的多选下拉框。这个扩展可能包括了新的配置项、模板修改、事件处理、数据模型、...
ExtJS 4 下拉树(TreeCombo)是一种组合控件,它将传统的下拉框与树形结构结合在一起,提供了一种在有限空间内展示层级数据的高效方式。这种控件在很多场合都非常实用,例如在需要用户选择分类或者层级结构的场景中...
ExtJs4.2没有直接提供下拉树这个组件,但是有例子可以用,文件位置:ext-4.2.1.883\examples\ux\TreePicker.js 但是它有点小毛病吧:默认显示了根节点;达到最小高度时再展开节点,高度不能自动调整。 所以我做了一...
ExtJs3下拉树 分两种方式调用:第一种: xtype : 'combotree', name : 'dm', fieldLabel : 'dm', tree : this.ct this.ct = new Ext.tree.TreePanel({ autoScroll : true, height : 250, border : false, ...
在ExtJS 3中,多选下拉框(LovCombo)是一种复合组件,它结合了下拉列表和“爱好者选择”(LOV,Lookup Value)的功能,允许用户在多个选项中进行复选选择。在Web应用中,这种组件常用于数据输入,特别是在数据库...
该资源主要展示了在Extjs6中Combobox控件实现下拉选择多个数据的功能
综上所述,ExtJS 4.x的ComboboxTree组件是实现下拉树形菜单的强大工具,它结合了下拉框的简洁和树结构的层次感,提供了丰富的定制选项,能满足多种场景下的需求。理解并熟练掌握其用法,将极大地提升开发效率和用户...
本教程将深入讲解如何实现EXTJS4下的下拉菜单树,并支持单选和多选功能。 1. **EXTJS4的基础概念** - EXTJS是一个基于JavaScript的富客户端框架,提供了一系列强大的组件库,可以构建复杂的、数据驱动的Web应用...
在ExtJS中,下拉树(ComboBoxTree)是一种结合了下拉框和树结构的组件,它允许用户从一个展开的树形列表中选择值,而不是传统的单行文本输入或简单的下拉列表。这种组件在数据层级结构复杂且需要用户进行多级选择时...
标题中的“Extjs4 下拉树”指的是EXTJS框架中的一个组件,用于实现下拉菜单与树形结构的结合,这种组件通常在需要选择层级结构数据时非常有用,比如地区选择、组织架构选择等。EXTJS是Sencha公司开发的一个...
在EXTJS4中,实现一个下拉树(Combobox Tree)并支持多选和复选功能,主要是通过自定义组件(Ext.define)来完成的。这个组件继承自EXTJS的Picker字段(Ext.form.field.Picker),并添加了树形结构和复选功能。以下...
ExtJS下拉树是一种在Web应用中常用的交互组件,它结合了下拉框和树形结构的优点,使得用户可以在一个紧凑的空间内选择嵌套层次的数据。这种组件在数据层级较多,需要用户进行逐级选择或者查看层级关系时非常实用。在...
### ExtJS4 下拉树组件知识点详解 #### 一、概述 在ExtJS4中,下拉树组件(TreeComboBox)是一种特殊的组合框,它结合了下拉列表和树形结构的功能,允许用户通过选择树节点来填充组合框的值。这种组件广泛应用于...
通过研究和理解"ExtJS日期多选组件源码",开发者可以深入学习ExtJS组件设计、事件处理、数据绑定等核心概念,并能进一步定制适合自己项目需求的日期选择组件。这样的组件对于提高开发效率和用户体验具有积极的意义。
利用extjs6自带的treePicker插件,实现下拉树的效果
Extjs 模拟下拉多选checkbox