• 动态生成决策树


    自己写之前,也上网搜过,不过没找到,所以现在将自己的代码发出来,希望可以帮到朋友们。

    功能如下:

    这里的弹出框调用的是bootsrap的组件,所以代码仅供参考,复制上去功能是出不来的,js具体代码如下:

    /**
     * Created by heshuaishuai on 2017/3/6.
     */
    define(
        [ "PDUtilDir/grid", "PDUtilDir/util", "PDUtilDir/tool",
            "PDUtilDir/dialog", "PDUtilDir/searchBlock",
            "CommonUtilDir/dict",
            "CommonUtilCkEditorDir/ckeditor","Date", "DateCN", "css!DateCss"  ],
        function(Grid, Util, Tool, Dialog, SearchBlock ,Dict) {
            //定义html全局变量
            var html = '';
            //定义一个具有初始值的json
            var treeJson = {
                ruleId:"",
                name:"规则",
                expression:"",
                id:"root"
    
            };
    
            /**
             * 创建根节点
             */
            function buildRoot(){
                html += '<div class="root" id="root">';
                html +=    '<span class="name btn btn-default">规则</span>';
                html +=    '<ul></ul>';
                html += '</div> ';
                return html;
            }
    
            /**
             * 创建左右分支
             */
            function bulidBranch(node) {
                branchStyle();
                html += '<div class="left" id='+node.yes.id+'>';
                html +=     '<span class="name btn btn-default"></span>';
                html +=        '<ul></ul>';
                html += '</div>';
                html += '<div class="right" id='+node.no.id+'>';
                html +=     '<span class="name btn btn-default"></span>';
                html +=        '<ul></ul>';
                html += '</div>';
                return html;
            }
    
            /**
             * 分支样式
             */
            function branchStyle(){
                html += '<div>';
                html +=     '<span class="vertical_left">成立</span>';
                html +=        '<span class="vertical_right">不成立</span>';
                html +=        '<span class="tran_left"></span>';
                html +=        '<span class="tran_right"></span>';
                html += '</div>';
                return html;
            }
    
            /**
             * 计算分支样式长度
             */
            function branchWidth(id){
                var array = id.split('-');
                var i = array.length-1;
                var w = $('#'+id+'>span.name').outerWidth();
                $('#'+id).width(w);
                if($('#'+id).attr('class') === 'left'){
                    var parents_w = $('#'+id).parent('ul').parent('div').outerWidth();
                    $('#'+id).css({'left':-(250-parents_w/2+w/2)+(i-1)*50+'px'});
                }
                if($('#'+id).attr('class') === 'right'){
                    var parents_w = $('#'+id).parent('ul').parent('div').outerWidth();
                    $('#'+id).css({'right':-(250-parents_w/2+w/2)+(i-1)*50+'px'});
                }
                $('#'+id+'>ul>div>span.tran_left').css({
                    'width':250-i*50+'px',
                    'left':-(250-w/2)+i*50+'px'
    
                });
                $('#'+id+'>ul>div>span.tran_right').css({
                    'width':250-i*50+'px',
                    'right':-(250-w/2)+i*50+'px'
                });
                $('#'+id+'>ul>div>span.vertical_left').css({
                    'width':250-i*50+'px',
                    'left':-(250-w/2)+i*50+'px'
    
                });
                $('#'+id+'>ul>div>span.vertical_right').css({
                    'width':250-i*50+'px',
                    'right':-(250-w/2)+i*50+'px'
                });
                $('#'+id+'>ul>div.left').css({'left':-(250-w/2+50)+i*50+'px'});
                $('#'+id+'>ul>div.right').css({'right':-(250-w/2+50)+i*50+'px'});
            }
    
            /**
             * 动态生成json
             */
            function createJson( id , nodeObj , name , expression ){
                var node = findNode(id , nodeObj );
                node.expression = expression;
                node.name = name;
                node['yes'] = {
                    name:"",
                    id:node.id+'-true',
                    expression:""
                },
                    node['no'] = {
                        name:"",
                        id:node.id+'-false',
                        expression:""
                    }
            }
    
    
            /**
             * 核心算法:深度先序遍历获取当前node
             */
            function findNode( id , node ){
                //递归
                if( node ){
                    if( node.id == id )
                        return node;
                    if( node.yes ){
                        var tempNode = findNode( id , node.yes);
                        if( tempNode && tempNode.id == id )
                            return tempNode;
                    }
                    if( node.no){
                        var tempNode = findNode( id , node.no);
                        if( tempNode && tempNode.id == id )
                            return tempNode;
                    }
                }
                return false;
            }
    
            /**
             * 获取高亮事件
             */
            function bindFocusEvent( id ){
                $('#' + id + '>span' ).unbind('click').bind( 'click' , function(){
                    resetButtonStyle();
                    $(this).addClass('btn-primary').removeClass('btn-default');
                });
    
            }
    
            /**
             * 点击添加条件表达式事件
             */
            function bindAddConditionButtonEvent(node){
                $('#add').unbind('click').bind('click' , function(){
                    var currentNodeId = $('.btn-primary').parent('div').attr('id');
                    if($('#'+currentNodeId+'>ul').html() ===''){
                        popUpAddConditionDialog( currentNodeId,node );
                    }
                });
            }
    
            /**
             * 调用添加表达式弹出框,返回json,动态渲染
             */
            function popUpAddConditionDialog( id,node ){
                var currentNode = findNode( id , node );
                var buttons = [];
                buttons.push(
                    {
                        name:"确定",
                        //回调函数
                        callback:function(){
                            var name = $('#conditionName').val();
                            var expression = $('#conditionExpression').val();
                            if(name === '' && expression === ''){
                                notNullDialog('条件名称与条件表达式不能为空!');
                            }else if(name === ''){
                                notNullDialog('条件名称不能为空!');
                            }else if(expression === ''){
                                notNullDialog('条件表达式不能为空!');
                            }else{
                                $('#' + id + ' >span').text(name);
                                createJson( id , currentNode , name , expression);
                                dialog.hide();
                                html = '';
                                $('#' + id + '>ul').empty();
                                $('#' + id + '>ul').append(bulidBranch(currentNode));
                                var childYesId = $('#' + id + ' >ul>.left').attr('id');
                                var childNoId = $('#' + id + ' >ul>.right').attr('id');
                                bindFocusEvent( childYesId );
                                bindFocusEvent( childNoId );
                                branchWidth(id);
                            }
    
    
                        }
                    }
                );
    
                var dialog = Dialog({
                    id:"BaseDialog",
                    cache:false,
                    title:"条件内容",
                    "400px",
                    hieght:"200px",
                    dialogsize:"modal-sm",
                    body:"",
                    buttons:buttons
                });
    
                var dialogHtml = '';
                dialogHtml += '<form class="form-horizontal">';
                dialogHtml +=     '<div class="form-group">';
                dialogHtml +=        '<label class="col-sm-3">条 件 名 称:</label>';
                dialogHtml +=        '<input id="conditionName" class="col-sm-8" type="text"';
                dialogHtml +=        'placeholder="Conditional name" maxlength="20"/>';
                dialogHtml +=    '</div>';
                dialogHtml +=     '<div class="form-group">';
                dialogHtml +=        '<label class="col-sm-3">条件表达式:</label>';
                dialogHtml +=        '<textarea id="conditionExpression" class="col-sm-8"';
                dialogHtml +=        'placeholder="Conditional expression" maxlength="200"';
                dialogHtml +=        'rows="3"></textarea>';
                dialogHtml +=    '</div>';
                dialogHtml += '</form>';
                dialog.setBody(dialogHtml);
                dialog.show();
            }
    
            /**
             * 点击设置结果事件
             */
            function bindSetResultButtonEvent(node){
                $('#result').unbind('click').bind('click' , function(){
                    var currentNodeId = $('.btn-primary').parent('div').attr('id');
                    if($('#'+currentNodeId+'>ul').html() ===''){
                        popUpSetResultDialog( currentNodeId ,node);
                    }
                });
            }
    
            /**
             *     调用设置结果弹出框
             */
            function popUpSetResultDialog( id ,node){
                var currentNode = findNode( id , node );
                var buttons = [];
                buttons.push(
                    {
                        name:"确定",
                        //回调函数
                        callback:function(){
                            var name = $('#resultName').val();
                            var expression = $('#resultExpression').val();
                            if(name === '' && expression === ''){
                                notNullDialog('结果名称与结果表达式不能为空!');
                            }else if(name === ''){
                                notNullDialog('结果名称不能为空!');
                            }else if(expression === ''){
                                notNullDialog('结果表达式不能为空!');
                            }else{
                                $('#' + id + ' >span').text(name);
                                currentNode.name = name;
                                currentNode.expression = expression;
                                branchWidth(id);
                                dialog.hide();
                            }
    
    
                        }
    
                    }
                );
    
                var dialog = Dialog({
                    id:"BaseDialog",
                    cache:false,
                    title:"设置结果",
                    "400px",
                    hieght:"200px",
                    dialogsize:"modal-sm",
                    body:"",
                    buttons:buttons
                });
    
                var dialogHtml = '';
                dialogHtml += '<form class="form-horizontal">';
                dialogHtml +=     '<div class="form-group">';
                dialogHtml +=        '<label class="col-sm-3">结 果 名 称:</label>';
                dialogHtml +=        '<input id="resultName" class="col-sm-8" type="text"';
                dialogHtml +=        'placeholder="Result name" maxlength="20"/>';
                dialogHtml +=    '</div>';
                dialogHtml +=     '<div class="form-group">';
                dialogHtml +=        '<label class="col-sm-3">结果表达式:</label>';
                dialogHtml +=        '<textarea id="resultExpression" class="col-sm-8"';
                dialogHtml +=        'placeholder="Result expression" maxlength="200"';
                dialogHtml +=        'rows="3"></textarea>';
                dialogHtml +=    '</div>';
                dialogHtml += '</form>';
                dialog.setBody(dialogHtml);
                dialog.show();
            }
    
            /**
             * 点击删除事件
             */
            function bindDeleteButtonEvent(node){
                $('#delete').unbind('click').bind('click' , function(){
                    var currentNodeId = $('.btn-primary').parent('div').attr('id');
                    var ulHtml = $('#'+currentNodeId+'>ul').html();
                    if(ulHtml !=='' && ulHtml !==undefined){
                        popUpDeleteDialog( currentNodeId ,node);
                    }
                });
            }
    
            /**
             *     调用删除弹出框
             */
            function popUpDeleteDialog( id ,node){
                var currentNode = findNode( id , node );
                var buttons = [];
                buttons.push(
                    {
                        name:"确定",
                        //回调函数
                        callback:function(){
                            $('#'+id+' ul').empty();
                            $('#' + id + ' >span').text('');
                            currentNode.name = '';
                            currentNode.expression = '';
                            delete currentNode.yes;
                            delete currentNode.no;
                            dialog.hide();
                        }
    
                    }
                );
    
                var dialog = Dialog({
                    id:"BaseDialog",
                    cache:false,
                    title:"添加内容",
                    "400px",
                    hieght:"200px",
                    dialogsize:"modal-sm",
                    body:"确定删除吗?",
                    buttons:buttons
                });
                dialog.show();
            }
    
            /**
             * 调用不能为空弹出框
             */
            function notNullDialog( text ){
                var buttons = [];
                buttons.push(
                    {
                        name:"确定",
                        //回调函数
                        callback:function(){
                            dialog.hide();
                        }
    
                    }
                );
    
                var dialog = Dialog({
                    id:"BaseDialog",
                    cache:false,
                    title:"提示",
                    "300px",
                    hieght:"100px",
                    dialogsize:"modal-sm",
                    body:text,
                    buttons:buttons
                });
                dialog.show();
            }
    
            /**
             * 重置样式
             */
            function resetButtonStyle(){
                $('#decisionTree .btn-primary').addClass('btn-default').removeClass('btn-primary');
            }
    
            /**
             * 根据json,深度遍历生成DOM结构
             */
            function generateDecisionTree(node){
                if(node){
                    var suffix = branchPosition(node.id);
                    if(suffix === 'root'){
                        html += '<div class="root" id='+node.id+'><span class="name btn btn-default">'+node.name+'</span><ul>';
                    }
    
                    if(node.yes && node.no){
                        if(suffix === 'true'){
                            html += '<div class="left" id='+node.id+'><span class="name btn btn-default">'+node.name+'</span><ul>';
                        }else if(suffix === 'false'){
                            html += '<div class="right" id='+node.id+'><span class="name btn btn-default">'+node.name+'</span><ul>';
                        }
                        branchStyle();
                    }else{
                        if(suffix === 'true'){
                            html += '<div class="left" id='+node.id+'><span class="name btn btn-default">'+node.name+'</span><ul>';
                        }else if(suffix === 'false'){
                            html += '<div class="right" id='+node.id+'><span class="name btn btn-default">'+node.name+'</span><ul>';
                        }
                    }
    
                    if(node.yes){
                        generateDecisionTree(node.yes);
                    }
                    if(node.no){
                        generateDecisionTree(node.no);
                    }
                    html +='</ul></div>';
                }
                return html;
            }
    
            /**
             * 根据id后缀,判断左右分支
             */
            function branchPosition(id){
                var array = id.split('-');
                var length = array.length;
                var suffix = array[length-1];
                return suffix;
            }
    
            /**
             * 深度遍历:渲染后获取焦点
             */
            function getRenderFocus(node){
                bindFocusEvent( node.id );
                branchWidth(node.id);
                if(node.yes){
                    getRenderFocus(node.yes);
                }
                if(node.no){
                    getRenderFocus(node.no);
                }
            }
    
            /**
             * 点击生成,渲染页面
             */
            function bindGenerateButtonEvent(){
                $('#generate').unbind('click').bind('click',function(){
                    html = '';
                    $('#decisionTree').empty();
                    $('#decisionTree').html(generateDecisionTree(treeJson));
                    getRenderFocus(treeJson);
                });
            }
    
            /**
             * 点击保存,弹出json字符串
             */
            function bindSaveButtonEvent(node){
                $('#save').bind('click',function(){
                    var treeString = JSON.stringify(node);
                    alert(treeString);
                });
            }
    
            /**
             * 初始化数据
             */
            function initData(){
                $.ajax({
                    type:'GET',
                    url:getServer()+'/static/app/collection/decisionTree/treeJson.json',
                    dataType:'JSON',
                    success:function(data){
                        if(data){
                            if(data.ruleId === ''){
                                $('#decisionTree').html(buildRoot());
                                bindFocusEvent( 'root' );
                                init(treeJson);
                            }else{
                                html = '';
                                $('#decisionTree').empty();
                                $('#decisionTree').html(generateDecisionTree(data));
                                getRenderFocus(data);
                                init(data);
                            }
                        }
                    }
                });
            }
            /**
             * 初始化
             */
            function init(node){
                bindAddConditionButtonEvent(node);
                bindSetResultButtonEvent(node);
                bindDeleteButtonEvent(node);
                bindSaveButtonEvent(node);
            }
    
            /**
             * 主函数
             */
            return {
                mainInit : initData
            }
        });

    代码里三次用到了二叉树的先序遍历算法,核心算法也是二叉树的递归遍历算法,二叉树的递归遍历方法前面有说过。

    还有朋友们可能会问我这个gif图是怎么录制的,给大家推荐一款神器LICEcap。

  • 相关阅读:
    翘边阴影
    原生js实现 拖拽事件
    js实现计算器
    js实现选项卡
    js随机生成座号
    1.记住密码 提示框
    媒体查询
    高性能JavaScript 读书笔记
    調用WEB services
    Dragon Quest VIII 流程攻略(繁体中文完结版)
  • 原文地址:https://www.cnblogs.com/hess/p/6626226.html
Copyright © 2020-2023  润新知