后台的前端ExtJS的多选下拉树整理

/**
* 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));
}
}
});
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值