ExtJS帶複選框的下拉樹對複選框中半選狀態的實現

Extjs基本組件:帶複選框的下拉樹javascript

        首先,咱們對於ExtJs實現的帶複選框的下拉樹應該有一個簡單的瞭解,從下面的例子中能夠看出,treepanel是經過節點中checked的值(true,false)來實現複選框的兩種狀態(勾選,不選)的。css

代碼段:java

Ext.create('Ext.window.Window', {
	title: 'Test',
    height: 230,
    width: 400,
    layout: 'fit',
	autoShow:true,
    items: {
        xtype: 'treepanel',
        store: Ext.create('Ext.data.TreeStore', {
		    root: {
		        expanded: true,
		        children: [
		            { text: 'child1', leaf: true, checked: false},
		            { text: 'child2', expanded: true, checked: false, children: [
		                { text: 'child2-1', expanded: true, checked: false, children:[
		                 	{ text: 'child2-1-1', leaf: true, checked: true},
		                 	{ text: 'child2-1-2', leaf: true, checked: false}
		            	] },
		            	{ text: 'child2-2', leaf: true, checked: true}
		            ] },
		            { text: 'child3', leaf: true, checked: false }
		        ]
		    }
		}),
    	rootVisible: false
 	}
});

展現圖:node


半選的實現原理app

        其實實現checkbox半選很簡單,首先咱們應該知道,顯示在界面上的效果不過就是一張圖片而已,而checked的值(true/false)就像兩個開關同樣,隨着值得改變,由css樣式去更改圖片;而咱們如今要作的就是在此基礎上再加一個開關(indeterminate),優先級比checked高,當indeterminate = true時,由css樣式去更改咱們本身的半選圖片,indeterminate = false時,由checked去負責複選框的選中和不選兩種狀態。ide

        須要注意的一點就是,因爲點擊半選的複選框時,複選框須要處於不選狀態中,因此當複選框處於半選狀態時,checked此時應該等於true。ui

       

ok,從上面的原理能夠看出咱們實現半選的幾個難點:this

  1. 隨着checkbox的點擊,正確的改變節點中checked和indeterminate的值
  2. 根據checked和indeterminate的值如何修改樣式

那麼,該怎麼解決呢?url

自定義組件code

        組件的自定義封裝是Extjs的基本功了,咱們須要封裝一個組件來實現咱們上述的難點1

Ext.define('component.CheckTree', {
	extend: 'Ext.tree.Panel',
	requires: [
		'Ext.data.TreeStore'
	],
	xtype: 'checktree',
	store: {},
	rootVisible: false,
	useArrows: true,
	frame: true,
	title: 'Check Tree',
	header: false,
	bufferedRenderer: false,
	animate: true,
	minHeight: 200,
	maxHeight: 200,
	bodyStyle: 'overflow-x:no; overflow-y:auto',
	SELSTATUS: {
		NONE: 0,      //沒有選中
		HALFSEL: 1,    //半選
		ALLSEL: 2      //全選
	},

	listeners: {
		checkchange: function(node, checked) {
			this.setChildChecked(node, checked);
			this.setParentChecked(node, checked);
		}
	},

	initComponent: function() {
		Ext.apply(this, {
			store: this.store,
		});
		this.callParent();
	},
	
	//遍歷全部子節點,全選或全不選全部子節點,indeterminate設置爲false
	setChildChecked: function(node, checked) {
		var me = this;
		node.expand();
		node.set('indeterminate', false);
		node.data.checked = !checked;
		node.set('checked', checked);
		if (node.hasChildNodes()) {
			node.eachChild(function(child) {
				this.setChildChecked(child, checked);
			}, me)
		}
	},
	
	//遍歷全部的父節點,設置複選框的三種狀態  
    //注意:checked的set方法只有在當前值與要改變的值不一樣時,纔回去修改樣式
	setParentChecked: function(node, checked, selStatus) {
		var me = this,
			parentNode = node.parentNode,
			isHalfSel = false, //半選
			isAllSel = false, //全選
			isNone = true,
			indeterminate,
			checkedArr = [],
			indexT, indexF;
			
		if (parentNode) {
			if(typeof(selStatus) == 'number'){
				switch (selStatus){
					case 0:
						node.set('indeterminate', false);
						node.data.checked = true;
						node.set('checked', false);
						me.setParentChecked(node, checked, null);
						break;
					case 1:
						node.set('indeterminate', true);
						node.data.checked = false;
						node.set('checked', true);
						me.setParentChecked(parentNode, checked, me.SELSTATUS['HALFSEL']);
						break;
					case 2:
						node.set('indeterminate', false);
						node.data.checked = false;
						node.set('checked', true);
						me.setParentChecked(node, checked, null);
						break;
					default:
						break;
				}
			}else{
				selStatus = null;
				parentNode.eachChild(function(childnode) {
					indeterminate = childnode.get('indeterminate');
					if (typeof(indeterminate) == 'boolean' && indeterminate) {
						selStatus = me.SELSTATUS['HALFSEL'];
					}
					if(!isHalfSel){
						checkedArr.push(childnode.get('checked'));
					}
				});
				if(!selStatus){
					indexT = checkedArr.indexOf(true);
					indexF = checkedArr.indexOf(false);
					switch (true){
						case  -1 == indexT:
							selStatus = me.SELSTATUS['NONE'];
							break;
						case  -1 == indexF:
							selStatus = me.SELSTATUS['ALLSEL'];
							break;
						default:
							selStatus = me.SELSTATUS['HALFSEL'];
							break;
					}
				}
				me.setParentChecked(parentNode, checked, selStatus);
			}
		}
	}
});

 

樣式的添加與控制

        已經來到了最後一步,黎明的曙光即將到來。

        首先,咱們須要明確幾點:

            1.  只有當node.set('checked', true/false),而且node.get('checked')的值與改變的值不一樣時,纔會去修改樣式;

            2.  當複選框爲不選狀態的時候,checkboxCls = ‘.x-tree-checkbox’ ,當爲選中的時候,checkboxCls = ‘.x-tree-checkbox  .x-tree-checkbox-checked’ 

.x-tree-checkbox-checked {
    background-position: 0 -15px;
}

.x-tree-checkbox {
    margin-right: 4px;
    top: 5px;
    width: 15px;
    height: 15px;
    background-image: url(images/form/checkbox.png);
}

            

ok,說了這麼多,相信你們的思路應該比較清晰了,經過set方法進入源碼,能夠發現能夠在Ext.tree.Column中的treeRenderer方法添加咱們須要的樣式,那麼,咱們能夠重寫這個方法,其中.x-tree-checkbox-indeterminate是咱們實現半選的樣式

代碼段:

Ext.define('Ext.overrides.tree.Column', {
	override: 'Ext.tree.Column',
	
	treeRenderer: function(value, metaData, record, rowIdx, colIdx, store, view) {
        var me = this,
            cls = record.get('cls'),
            rendererData;
        // The initial render will inject the cls into the TD's attributes.
        // If cls is ever *changed*, then the full rendering path is followed.
        if (metaData && cls) {
            metaData.tdCls += ' ' + cls;
        }
        rendererData = me.initTemplateRendererData(value, metaData, record, rowIdx, colIdx, store, view);
        
        //導航樹複選框的半選狀態實現
        var indeterminate = record.get('indeterminate');
        if('boolean' === typeof(indeterminate) && indeterminate){
        	rendererData.checkboxCls += ' x-tree-checkbox-indeterminate';
        }
        
        return me.getTpl('cellTpl').apply(rendererData);
    }
});

            

固然,.x-tree-checkbox-indeterminate是不存在的,是咱們本身須要的,要達到咱們的目的,就要讓組件在渲染時,可以找到它,所以,咱們能夠在主題中給該組件添加這個樣式,並把.x-tree-checkbox中的圖片文件改爲咱們須要的

.x-tree-checkbox {
    margin-right: 4px;
    top: 5px;
    width: 15px;
    height: 15px;
    background-image: url(images/form/checkbox1.png);
}

.x-tree-checkbox-indeterminate {
    background-position: 0 -30px;
}

 

半選實現

代碼段:

Ext.create('Ext.window.Window', {
	title: 'Test',
    height: 230,
    width: 400,
    layout: 'fit',
	autoShow:true,
    items: {
        xtype: 'checktree',
        store: Ext.create('Ext.data.TreeStore', {
		    root: {
		        expanded: true,
		        children: [
		            { text: 'child1', leaf: true, checked: false, indeterminate: false},
		            { text: 'child2', expanded: true, checked: false, indeterminate: false, children: [
		                { text: 'child2-1', expanded: true, checked: false, indeterminate: false, children:[
		                 	{ text: 'child2-1-1', leaf: true, checked: false, indeterminate: false},
		                 	{ text: 'child2-1-2', leaf: true, checked: false, indeterminate: false}
		            	] },
		            	{ text: 'child2-2', leaf: true, checked: false, indeterminate: false}
		            ] },
		            { text: 'child3', leaf: true, checked: false, indeterminate: false}
		        ]
		    }
		}),
    	rootVisible: false
 	}
});

點擊後的效果:

相關文章
相關標籤/搜索