日前做一个用户权限管理的页面,权限是一个树形结构,每个节点前是一checkbox,其状态表示 
用户是否具有该权限,当切换用户时,根据选择用户的权限设置树形的相应节点,保存时根据当 
前用户的选中情况保存数据。 

 

画面如下:

 带checkbox的TreeView的赋值与读值

其间主要碰到三个问题 

 

1)带checkbox的TreeView的显示 
2)根据用户权限数据对权限树赋值 
3)根据树形中checkbox的状态获取权限数据 

其解决办法如下: 
1) 

HTML中展现TreeView的div需要将class设为"ygtv-checkbox" 

Html代码 
<div id="divMenuTree" class="ygtv-checkbox"></div>  

 

另外javascript里要做如下处理(详细功用参见注释): 

Javascript代码 
menuTree = new YAHOO.widget.TreeView("divMenuTree", treeJSON);  
//点击节点时变换checkbox状态  
menuTree.subscribe('clickEvent', menuTree.onEventToggleHighlight);  
//节点状态变化时相应改变其父、子节点的状态  
menuTree.setNodesProperty('propagateHighlightUp', true);  
menuTree.setNodesProperty('propagateHighlightDown', true);  

     

    2) 
    可以用TreeView的getNodeByIndex或者getNodeByProperty取得节点,然后 
    使用Node的unhighlight不选,用highlight选中节点,代码片段如下: 

    Javascript代码 
    //清除所有checkbox  
    for(var i=1; i<=menuTree.getNodeCount(); i++) {  
        menuTree.getNodeByIndex(i).unhighlight(true);  
    }  
    //设定当前用户的权限  
    //只勾选叶子节点的checkbox,它们的上级节点状态会自动跟着变化,不用设置  
    for(var i=0; i<menus.size(); i++) {  
        var node = menuTree. getNodeByProperty('data', menus[i]);  
        if (!node.hasChildren(true)) {  
            node.highlight(false);  
        }  
    }  
    
    

    在设定当前用户的权限时,非叶子节点的状态可能是选中、部分选中和未选中,我 
    们不必自己判断,只要仅对叶子节点进行设置,然后让YUI自己去改变其上级节点状 
    态就可以了。 
    其中unhighlight,highlight的参数表示是否不改变该节点的上下级节点状态,在 
    清除所有checkbox时不需要改变,但在设定当前用户的权限时正好可以利用这一功能。 

     

    3) 
    YUI的带checkbox的TreeView其实不是真正的checkbox,是用css切换图片实现的,所以 
    好像无法像一组checkbox一样直接取得选中信息(我是没找到),不过可以根据Node的 
    highlightState属性知道该节点的状态,其中0表示未选中,1未部分选中,2未选中,所 
    以下面这段代码可以将选中的权限的ID组成一个数组:

    Javascript代码

    var menuIDs = new Array();  
    var idx = 0;  
    for(var i=1; i<=menuTree.getNodeCount(); i++) {  
        var node = menuTree.getNodeByIndex(i);  
        if (node.highlightState > 0) {  
            menuIDs[idx] = node.data;  
            idx ++;  
        }  
    }  
    

     

    总的感觉YUI是一个比较全面的库,虽然写法有些繁琐,但作为一个还算面面俱到的库使用 
    起来还是感觉蛮不错的,我只是另外少数地方用到了prototype,感觉就它们俩一般问题都 
    能搞定了。 

     

    最后,贴出整个页面的代码,其中很多是和TreeView无关的代码。我和后台交互的是json 
    格式的数据,具体我就不说明了,根据代码也能猜出个大概其了。 

    Html代码 
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    
    <html>
    
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>JNOC OA</title>
        
        <link rel="stylesheet" type="text/css" href="http://www.cnblogs.com/js/yui_2.8.1/reset/reset.css">
        <link rel="stylesheet" type="text/css" href="http://www.cnblogs.com/js/yui_2.8.1/fonts/fonts.css">
        <link type="text/css" rel="stylesheet" href="http://www.cnblogs.com/css/common.css"/>
        
        <style type="text/css">     
            table#pageTable {
                width: 80%;
            }
            
            table#pageTable tr#user {
                background-color:#FFFFCC;
            }
            
            table#pageTable tr#privilege {
                background-color:#CCFFFF;
            }
            
            table#pageTable th {
                vertical-align: top;
            }
        </style>
        
        <script type="text/javascript" src="http://www.cnblogs.com/js/prototype_1.6.1/prototype.js"></script>
        <script type="text/javascript" src="http://www.cnblogs.com/js/yui_2.8.1/yahoo/yahoo.js"></script>
        <script type="text/javascript" src="http://www.cnblogs.com/js/yui_2.8.1/yuiloader/yuiloader.js"></script>
        <script type="text/javascript" src="http://www.cnblogs.com/js/common.js"></script>
        <script type="text/javascript">
            var menuTree;
            
            function showMenuTree() {
                YAHOO.util.Connect.setDefaultPostHeader(false);
                YAHOO.util.Connect.initHeader("Accept", "application/json", true);
                
                var request = YAHOO.util.Connect.asyncRequest('POST', JNOCOA_ROOT_PATH + '/menuInfo/getMenuJSON.do', {
                    success: function(resp){
                        var respJSON = resp.responseText.evalJSON();
                        if (respJSON.successed) {
                            var treeJSON = respJSON.returnObject.evalJSON();
                            menuTree = new YAHOO.widget.TreeView("divMenuTree", treeJSON);
                            menuTree.subscribe('clickEvent', menuTree.onEventToggleHighlight);
                            menuTree.setNodesProperty('propagateHighlightUp', true);
                            menuTree.setNodesProperty('propagateHighlightDown', true);
                            menuTree.render();
                        }
                        else {
                            alert(respJSON.errors[0].message);
                        }
                    },
                    failure: function(error){
                        alert("读取菜单数据错误:" + error.statusText);
                    }
                }, null);
            }
            
    	    function loadUsers() {
    	        YAHOO.util.Connect.setDefaultPostHeader(false);
    	        YAHOO.util.Connect.initHeader("Accept", "application/json", true);
    	        
    	        var request = YAHOO.util.Connect.asyncRequest('POST', JNOCOA_ROOT_PATH + '/userInfo/getAllUser.do', {
    	            success: function(resp){
    	                var respJSON = resp.responseText.evalJSON();
    	                if (respJSON.successed) {
    		                users = respJSON.returnObject;
    		                var seleUser = $("userList");
    	                    for (var i=0; i<users.length; i++) {
    		                    oOption = document.createElement('option');
    		                    oOption.appendChild(document.createTextNode(users[i].name));
    		                    oOption.setAttribute('value', users[i].id);
    		                    seleUser.appendChild(oOption);
    	                    }
    
    	                    YAHOO.util.Event.addListener(seleUser, "change", refreshPrivilege);
    	                }
    	                else {
    	                    alert(respJSON.errors[0].message);
    	                }
    	            },
    	            failure: function(error){
    	                alert("读取用户数据错误:" + error.statusText);
    	            }
    	        }, null);
    	    }
    
    	    function refreshPrivilege() {
    		    var selectedIdx = this.selectedIndex;
    		    var userID = parseInt(this.options[selectedIdx].getAttribute('value'));
    
    		    //准备POST数据:用户ID
    		    var data = $H( { id : userID }).toJSON();
    		    
                YAHOO.util.Connect.setDefaultPostHeader(false);
                YAHOO.util.Connect.initHeader("Accept", "application/json", true);
                YAHOO.util.Connect.initHeader("Content-Type", "application/json; charset=utf-8", true);
                
                var request = YAHOO.util.Connect.asyncRequest('POST', JNOCOA_ROOT_PATH + '/privilege/get.do', {
                    success: function(resp){
                        var respJSON = resp.responseText.evalJSON();
                        if (respJSON.successed) {
                            menus = respJSON.returnObject.menuIDs;
                            //清除所有checkbox
                            for(var i=1; i<=menuTree.getNodeCount(); i++) {
                            	menuTree.getNodeByIndex(i).unhighlight(true);
                            }
                            //勾选叶子节点的checkbox,它们的上级节点状态会自动跟着变化,不用设置
                            for(var i=0; i<menus.size(); i++) {
                                var node = menuTree. getNodeByProperty('data', menus[i]);
                                if (!node.hasChildren(true)) {
                                    node.highlight(false);
                                }
                            }
                        } else {
                            alert(respJSON.errors[0].message);
                        }
                    },
                    failure: function(error){
                        alert("读取用户权限数据错误:" + error.statusText);
                    }
                }, data);
    	    }
    
    	    function savePrivilege() {
    		    if (!menuTree) {
    			    return;
    		    }
    
    		    var selectedIdx = $('userList').selectedIndex;
    		    var userID = parseInt($('userList').options[selectedIdx].getAttribute('value'));
    		    var menuIDs = new Array();
    		    var idx = 0;
                for(var i=1; i<=menuTree.getNodeCount(); i++) {
                    var node = menuTree.getNodeByIndex(i);
                    if (node.highlightState > 0) {
                        menuIDs[idx] = node.data;
                        idx ++;
                    }
                }
    
                var data = $H( { userID : userID, menuIDs : menuIDs }).toJSON();
    
                YAHOO.util.Connect.setDefaultPostHeader(false);
                YAHOO.util.Connect.initHeader("Accept", "application/json", true);
                YAHOO.util.Connect.initHeader("Content-Type", "application/json; charset=utf-8", true);
                
                var request = YAHOO.util.Connect.asyncRequest('POST', JNOCOA_ROOT_PATH + '/privilege/change.do', {
                    success: function(resp){
                        var respJSON = resp.responseText.evalJSON();
                        if (respJSON.successed) {
                        	alert('已成功修改用户权限。');
                        } else {
                            alert(respJSON.errors[0].message);
                        }
                    },
                    failure: function(error){
                        alert("修改用户权限失败:" + error.statusText);
                    }
                }, data);
    	    }
    	    
    	    new YAHOO.util.YUILoader( {
    	        require : [ 'menu', 'event', 'connection', 'datasource', 'datatable', 'treeview' ],
    	        base : 'http://www.cnblogs.com/js/yui_2.8.1/',
    	        filter : 'RAW',
    	        onSuccess : function() {
    	            YAHOO.util.Event.onContentReady("menubar", function() {
    	                getMenu();
    	            });
    
    	            YAHOO.util.Event.onContentReady("userList", function() {
    	                loadUsers();
    	            });
    
                    YAHOO.util.Event.onContentReady("divMenuTree", function() {
                        showMenuTree();
                    });
    	        },
    	        onFailure : function(o) {
    	            alert("YUI模块加载错误: " + YAHOO.lang.dump(o));
    	        }
    	    }).insert();
        </script>
    </head>
    
    <body class="yui-skin-sam">
        <div ></div>
        <div >
            <div >
                <div class="bd">
                    <ul class="first-of-type">
                        <li class="yuimenubaritem first-of-type">
                            <a class="yuimenubaritemlabel">数据录入</a>
                        </li>
                        <li class="yuimenubaritem">
                            <a class="yuimenubaritemlabel">数据修改</a>
                        </li>
                        <li class="yuimenubaritem">
                            <a class="yuimenubaritemlabel">数据检索</a>
                        </li>
                        <li class="yuimenubaritem">
                            <a class="yuimenubaritemlabel">报表</a>
                        </li>
                        <li class="yuimenubaritem">
                            <a class="yuimenubaritemlabel">系统</a>
                        </li>
                    </ul>
                </div>
            </div>
        </div>
        <div >
            <div >用户权限管理</div>
            <table >
    			<tr >
    			    <th width="10%">用户:</th>
                    <td>
                        <select >
                            <option value="-1">请选择用户</option>
                        </select>
                        <button onclick="savePrivilege()">保存</button>
                    </td>
    			</tr>
                <tr >
                    <th>权限:</th>
                    <td><div ></div></td>
                </tr>
            </table>
        </div>
    
        <div >
            <table width="100%">
                <tr>
                    <td ></td>
                    <td width="500px"></td>
                    <td width="100px" align="right"><a href="javascript:logout();">退出</a></td>
                </tr>
            </table>
        </div>
    </body>
    
    </html>
    

    相关文章: