iteye_9568 2010-05-14 11:38
浏览 220
已采纳

邀请Ext爱好者一起解决授权树模型的问题

碰到一个问题解决不了,请大家帮分析一下!
问题是这样的,我要一个用来授权时候用的授权树,她的基本需求如下:
1.可以复选节点。
2.选中节点后要递归选中其所有子节点;取消选中状态后,要递归取消其所有子节点。
3.选中节点后腰递归选中所有直系父节点,如果某节点的所有子节点都被取消了则取消所有直系父节点的选中状态。

我目前已经实现了大部分功能(参考了E3项目授权树模型代码),但有一个Bug,选中某一叶子节点,则所有节点会被选中。

            /**
             * 监听节点的选中状态
             /
            tree.on('checkchange', function(pNode, pChecked) {
                        pNode.attributes.checked = pChecked;
                        /
*
                         * 说明:
                         * 下面这两个方法同时调用就回出现,选择一个叶子节点则所有节点都被选中的Bug
                         * 如果只是调用其中任一个方法,则选中子节点功能和选中父节点功能都是正常的
                         * 小弟水平有限,实在找不出问题所在,特请大家看看
                         /
                        checkChildren(pNode);
                        checkParents(pNode);

                    });

附件里面已经打包了Ext3.1的SDK,下载解压后便可以直接修改代码调试。有兴趣的可以看看!多谢!



部分代码如下:


/
*

  • 树模型测试
    */
    Ext.onReady(function() {
    Ext.QuickTips.init();
    Ext.form.Field.prototype.msgTarget = 'qtip';
    Ext.BLANK_IMAGE_URL = './resource/image/ext/s.gif';
    var node00 = new Ext.tree.TreeNode({
    text : '根节点00',
    expanded : true,
    checked : false,
    // leaf:false,
    id : '00'
    });
    var node0001 = new Ext.tree.TreeNode({
    text : '节点0001',
    expanded : true,
    checked : false,
    // leaf:false,
    id : '0001'
    });
    var node000101 = new Ext.tree.TreeNode({
    text : '节点000101',
    expanded : true,
    checked : false,
    // leaf:false,
    id : '000101'
    });
    var node000102 = new Ext.tree.TreeNode({
    text : '节点000102',
    expanded : true,
    checked : false,
    // leaf:true,
    id : '000102'
    });
    var node00010103 = new Ext.tree.TreeNode({
    text : '节点00010103',
    expanded : true,
    checked : false,
    // leaf:true,
    id : 'node00010103'
    });
    node00.appendChild(node0001);
    node0001.appendChild(node000101);
    node0001.appendChild(node000102);
    node000101.appendChild(node00010103);
    var tree = new Ext.tree.TreePanel({
    autoHeight : false,
    autoWidth : false,
    autoScroll : true,
    animate : false,
    rootVisible : true,
    title : '测试',
    border : false,
    containerScroll : true,
    applyTo : 'treeDiv',
    root : node00
    });
    node00.expand();
    var checkChildren = function(node) {
    if (node.isLeaf()) {// 非叶子节点
    return;
    }
    //alert('1');
    var nodeUI = node.getUI();
    var children = node.childNodes;
    //alert(children.length);
    for (var i = 0; i < children.length; i++) {
    var child = children[i];
    var childUI = child.getUI();
    if (typeof child.attributes.checked == 'undefined') continue;
    if (child.attributes.checked == node.attributes.checked) continue;
    childUI.toggleCheck(nodeUI.isChecked());
    child.attributes.checked = nodeUI.isChecked();
    checkChildren(child);
    }
    };

        /**
         * 递归选中父节点
         */
        var checkParents = function(node) {
            if (node == null) {
                return;
            }
            var nodeUI = node.getUI();
            if (typeof node.attributes.checked == 'undefined') {
                return;
            }
            if (node.attributes.checked == false) {// 取消父亲.
                uncheckParents(node);
                return;
            }
            var parentNode = node.parentNode;
            if (parentNode == null) {
                return;
            }
            var parentNodeUI = parentNode.getUI();
            if (typeof parentNode.attributes.checked == 'undefined') {
                return;
            }
            if (parentNode.attributes.checked) {// 已经选种
                return;
            }
            parentNodeUI.toggleCheck(true);
            parentNode.getOwnerTree().fireEvent('onChecked', parentNode);
            parentNode.attributes.checked = true;
            checkParents(parentNode);
        };
    
        /**
         * 递归取消父节点选中状态
         */
        var uncheckParents = function(node) {
            var parentNode = node.parentNode;
            if (parentNode == null) {
                return;
            }
            var parentNodeUI = parentNode.getUI();
            if (typeof parentNode.attributes.checked == 'undefined') {
                return;
            }
    
            var children = parentNode.childNodes;
            for (var i = 0; i &lt; children.length; i++) {
                var child = children[i];
                var childUI = child.getUI();
                if (typeof child.attributes.checked == 'undefined') {
                    continue;
                }
                if (child.attributes.checked == true) {
                    return;
                }
            }
            parentNodeUI.toggleCheck(false);
            parentNode.attributes.checked = false;
            parentNode.getOwnerTree().fireEvent('onUnchecked', parentNode);
            uncheckParents(parentNode);
        };
    
        /**
         * 监听节点的选中状态
         */
        tree.on('checkchange', function(pNode, pChecked) {
                    pNode.attributes.checked = pChecked;
                    /**
                     * 说明:
                     * 下面这两个方法同时调用就回出现,选择一个叶子节点则所有节点都被选中的Bug
                     * 如果只是调用其中任一个方法,则选中子节点功能和选中父节点功能都是正常的
                     * 小弟水平有限,实在找不出问题所在
                     */
                    checkChildren(pNode);
                    checkParents(pNode);
    
                });
    
    })
    

  • 写回答

4条回答 默认 最新

  • chem_zqm 2010-05-15 02:49
    关注

    [code="js"]
    function cascadeParent(){
    var pn = this.parentNode;
    if (!pn || !Ext.isBoolean(this.attributes.checked))
    return;
    if (this.attributes.checked) {//级联选中
    pn.getUI().toggleCheck(true);
    }
    else {//级联未选中
    var b = true;
    Ext.each(pn.childNodes, function(n){
    if (n.getUI().isChecked()){
    return b = false;
    }
    return true;
    });
    if (b)
    pn.getUI().toggleCheck(false);
    }
    pn.cascadeParent();
    }

    function cascadeChildren(){
        var ch = this.attributes.checked;
        if (!Ext.isBoolean(ch)) 
            return;
        Ext.each(this.childNodes, function(n){
    
            n.getUI().toggleCheck(ch);
            n.cascadeChildren();
        });
    }
    /**
     * 为TreeNode对象添加级联父节点和子节点的方法
     */
    Ext.apply(Ext.tree.TreeNode.prototype, {
        cascadeParent: cascadeParent,
        cascadeChildren: cascadeChildren
    });
    /**
     * Checkbox被点击后级联父节点和子节点
     */
    Ext.override(Ext.tree.TreeEventModel, {
        onCheckboxClick: Ext.tree.TreeEventModel.prototype.onCheckboxClick.createSequence(function(e, node){
            node.cascadeParent();
            node.cascadeChildren();
        })
    });
    

    [/code]
    把这段代码加到Ext.onReady(function() { 下面就可以实现级联了,其实就是为TreeNode添加两个级联函数,修改TreeEventModel的onCheckboxClick函数使得用户点击checkbox后进行级联,好处就是如果你是通过代码对选中状态进行设置级联方法是不会执行的

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(3条)

报告相同问题?

悬赏问题

  • ¥15 求chat4.0解答一道线性规划题,用lingo编程运行,第一问要求写出数学模型和lingo语言编程模型,第二问第三问解答就行,我的ddl要到了谁来求了
  • ¥15 Ubuntu在安装序列比对软件STAR时出现报错如何解决
  • ¥50 树莓派安卓APK系统签名
  • ¥15 maple软件,用solve求反函数出现rootof,怎么办?
  • ¥65 汇编语言除法溢出问题
  • ¥15 Visual Studio问题
  • ¥20 求一个html代码,有偿
  • ¥100 关于使用MATLAB中copularnd函数的问题
  • ¥20 在虚拟机的pycharm上
  • ¥15 jupyterthemes 设置完毕后没有效果