• easyui源码翻译1.32--Tree(树)


    前言

    使用$.fn.tree.defaults重写默认值对象。下载该插件翻译源码

    树控件在web页面中一个将分层数据以树形结构进行显示。它提供用户展开、折叠、拖拽、编辑和异步加载等功能。

    源码

     

    /**
     * jQuery EasyUI 1.3.2
     * 
     *翻译:qq 1364386878
     */
    (function ($) {
        //渲染样式
        function wrapTree(jq) {
            var tree = $(jq);
            tree.addClass("tree");
            return tree;
        };
        // 获取树数据
        function _getTreeData(jq) {
            var data = [];
            collectTreeData(data, $(jq));
            //递归获取节点
            function collectTreeData(nodes, ul) {
                ul.children("li").each(function () {
                    var li = $(this);
                    var node = $.extend({},
                        $.parser.parseOptions(this, ["id", "iconCls", "state"]),
                        { checked: (li.attr("checked") ? true : undefined) }); 
    
                    node.text = li.children("span").html();
                    if (!node.text) {
                        node.text = li.html();
                    }
                    var uls = li.children("ul");
                    if (uls.length) {
                        node.children = [];
                        collectTreeData(node.children, uls);//递归本事
                    }
                    nodes.push(node);
                });
            };
            return data;
        };
        //事件绑定
        function bindEvent(jq) {
            var options = $.data(jq, "tree").options;
            $(jq).unbind().bind("mouseover", function (e) { //鼠标移上事件
                var tt = $(e.target);
                var nodes = tt.closest("div.tree-node");
                if (!nodes.length) {
                    return;
                }
                nodes.addClass("tree-node-hover");
                if (tt.hasClass("tree-hit")) {
                    if (tt.hasClass("tree-expanded")) {
                        tt.addClass("tree-expanded-hover");
                    } else {
                        tt.addClass("tree-collapsed-hover");
                    }
                }
                e.stopPropagation();
            }).bind("mouseout", function (e) {//鼠标离开事件
                var tt = $(e.target);
                var nodes = tt.closest("div.tree-node");
                if (!nodes.length) {
                    return;
                }
                nodes.removeClass("tree-node-hover");
                if (tt.hasClass("tree-hit")) {
                    if (tt.hasClass("tree-expanded")) {
                        tt.removeClass("tree-expanded-hover");
                    } else {
                        tt.removeClass("tree-collapsed-hover");
                    }
                }
                e.stopPropagation();
            }).bind("click", function (e) {//单击节点事件
                var tt = $(e.target);
                var nodes = tt.closest("div.tree-node");
                if (!nodes.length) {
                    return;
                }
                if (tt.hasClass("tree-hit")) {
                    _toggle(jq, nodes[0]);
                    return false;
                } else {
                    if (tt.hasClass("tree-checkbox")) {
                        _check(jq, nodes[0], !tt.hasClass("tree-checkbox1"));
                        return false;
                    } else {
                        select(jq, nodes[0]);
                        options.onClick.call(jq, _getNode(jq, nodes[0]));
                    }
                }
                e.stopPropagation();
            }).bind("dblclick", function (e) {//双击结点事件
                var nodes = $(e.target).closest("div.tree-node");
                if (!nodes.length) {
                    return;
                }
                select(jq, nodes[0]);
                options.onDblClick.call(jq, _getNode(jq, nodes[0]));
                e.stopPropagation();
            }).bind("contextmenu", function (e) {//右键菜单
                var nodes = $(e.target).closest("div.tree-node");
                if (!nodes.length) {
                    return;
                }
                options.onContextMenu.call(jq, e, _getNode(jq, nodes[0]));
                e.stopPropagation();
            });
        };
        //禁用拖放功能
        function _disableDnd(jq) {
            var node = $(jq).find("div.tree-node");
            node.draggable("disable");
            node.css("cursor", "pointer");
        };
        //启用拖放功能
        function _enableDnd(jq) {
            var Tree = $.data(jq, "tree");
            var options = Tree.options;
            var tree = Tree.tree;
            Tree.disabledNodes = [];
            //拖动功能 设置
            tree.find("div.tree-node").draggable({
                disabled: false,
                revert: true,
                cursor: "pointer",
                proxy: function (_1d) {
                    var p = $("<div class="tree-node-proxy"></div>").appendTo("body");
                    p.html("<span class="tree-dnd-icon tree-dnd-no">&nbsp;</span>" + $(_1d).find(".tree-title").html());
                    p.hide();
                    return p;
                },
                deltaX: 15,
                deltaY: 15,
                onBeforeDrag: function (e) {
                    if (options.onBeforeDrag.call(jq, _getNode(jq, this)) == false) {
                        return false;
                    }
                    if ($(e.target).hasClass("tree-hit") || $(e.target).hasClass("tree-checkbox")) {
                        return false;
                    }
                    if (e.which != 1) {
                        return false;
                    }
                    $(this).next("ul").find("div.tree-node").droppable({ accept: "no-accept" });
                    var indent = $(this).find("span.tree-indent");
                    if (indent.length) {
                        e.data.offsetWidth -= indent.length * indent.width();
                    }
                },
                onStartDrag: function () {
                    $(this).draggable("proxy").css({ left: -10000, top: -10000 });
                    options.onStartDrag.call(jq, _getNode(jq, this));
                    var node = _getNode(jq, this);
                    if (node.id == undefined) {
                        node.id = "easyui_tree_node_id_temp";
                        _update(jq, node);
                    }
                    Tree.draggingNodeId = node.id;
                },
                onDrag: function (e) {
                    var x1 = e.pageX, y1 = e.pageY, x2 = e.data.startX, y2 = e.data.startY;
                    var d = Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
                    if (d > 3) {
                        $(this).draggable("proxy").show();
                    }
                    this.pageY = e.pageY;
                },
                onStopDrag: function () {
                    $(this).next("ul").find("div.tree-node").droppable({ accept: "div.tree-node" });
                    for (var i = 0; i < Tree.disabledNodes.length; i++) {
                        $(Tree.disabledNodes[i]).droppable("enable");
                    }
                    Tree.disabledNodes = [];
                    var _20 = _find(jq, Tree.draggingNodeId);
                    if (_20.id == "easyui_tree_node_id_temp") {
                        _20.id = "";
                        _update(jq, _20);
                    }
                    options.onStopDrag.call(jq, _20);
                }
            }).droppable({//拉伸插件设置
                accept: "div.tree-node",
                onDragEnter: function (e, source) {
                    if (options.onDragEnter.call(jq, this, _getNode(jq, source)) == false) {
                        setdndClass(source, false);
                        $(this).removeClass("tree-node-append tree-node-top tree-node-bottom");
                        $(this).droppable("disable");
                        Tree.disabledNodes.push(this);
                    }
                },
                onDragOver: function (e, source) {
                    if ($(this).droppable("options").disabled) {
                        return;
                    }
                    var pageY = source.pageY;
                    var top = $(this).offset().top;
                    var height = top + $(this).outerHeight();
                    setdndClass(source, true);
                    $(this).removeClass("tree-node-append tree-node-top tree-node-bottom");
                    if (pageY > top + (height - top) / 2) {
                        if (height - pageY < 5) {
                            $(this).addClass("tree-node-bottom");
                        } else {
                            $(this).addClass("tree-node-append");
                        }
                    } else {
                        if (pageY - top < 5) {
                            $(this).addClass("tree-node-top");
                        } else {
                            $(this).addClass("tree-node-append");
                        }
                    }
                    if (options.onDragOver.call(jq, this, _getNode(jq, source)) == false) {
                        setdndClass(source, false);
                        $(this).removeClass("tree-node-append tree-node-top tree-node-bottom");
                        $(this).droppable("disable");
                        Tree.disabledNodes.push(this);
                    }
                },
                onDragLeave: function (e, source) {
                    setdndClass(source, false);
                    $(this).removeClass("tree-node-append tree-node-top tree-node-bottom");
                    options.onDragLeave.call(jq, this, _getNode(jq, source));
                },
                onDrop: function (e, source) {
                    var target = this;
                    var action, point;
                    if ($(this).hasClass("tree-node-append")) {
                        action = moveNode;
                    } else {
                        action = insertNode;
                        point = $(this).hasClass("tree-node-top") ? "top" : "bottom";
                    }
                    action(source, target, point);
                    $(this).removeClass("tree-node-append tree-node-top tree-node-bottom");
                }
            });
    
            //设置拖动样式
            function setdndClass(source, dnd) {
                var dndicon = $(source).draggable("proxy").find("span.tree-dnd-icon");
                dndicon.removeClass("tree-dnd-yes tree-dnd-no").addClass(dnd ? "tree-dnd-yes" : "tree-dnd-no");
            };
    
            function moveNode(nodeEl, parent) {
                if (_getNode(jq, parent).state == "closed") {
                    expand(jq, parent, function () {
                        doMoveNode();
                    });
                } else {
                    doMoveNode();
                }
                function doMoveNode() {
                    var nodeData = $(jq).tree("pop", nodeEl);
                    $(jq).tree("append", { parent: parent, data: [nodeData] });
                    options.onDrop.call(jq, parent, nodeData, "append");
                };
            };
            function insertNode(nodeEl, parent, point) {
                var param = {};
                if (point == "top") {
                    param.before = parent;
                } else {
                    param.after = parent;
                }
                var nodeData = $(jq).tree("pop", nodeEl);
                param.data = nodeData;
                $(jq).tree("insert", param);
                options.onDrop.call(jq, parent, nodeData, point);
            };
        };
        //将节点设置为勾选或不勾选
        function _check(jq, target, isCheck) {
            var options = $.data(jq, "tree").options;
            if (!options.checkbox) {
                return;
            }
            var node2 = _getNode(jq, target);
            if (options.onBeforeCheck.call(jq, node2, isCheck) == false) {
                return;
            }
            var node = $(target);
            var ck = node.find(".tree-checkbox");
            ck.removeClass("tree-checkbox0 tree-checkbox1 tree-checkbox2");//清空样式
            if (isCheck) {
                ck.addClass("tree-checkbox1");//勾选样式
            } else {
                ck.addClass("tree-checkbox0");//不勾选样式
            }
            //设置级联选中
            if (options.cascadeCheck) {
                setParentsChecked(node);
                setChildrenChecked(node);
            }
            
            options.onCheck.call(jq, node2, isCheck);
            //勾选子结点
            function setChildrenChecked(node) {
                var ck = node.next().find(".tree-checkbox");
                ck.removeClass("tree-checkbox0 tree-checkbox1 tree-checkbox2");
                if (node.find(".tree-checkbox").hasClass("tree-checkbox1")) {
                    ck.addClass("tree-checkbox1");//勾选样式(非级联)
                } else {
                    ck.addClass("tree-checkbox0");//不勾选样式
                }
            };
            //级联勾选父结点
            function setParentsChecked(node) {
                var parentNode = _getParent(jq, node[0]);
                if (parentNode) {
                    var ck = $(parentNode.target).find(".tree-checkbox");
                    ck.removeClass("tree-checkbox0 tree-checkbox1 tree-checkbox2");
                    if (isAllSelected(node)) {
                        ck.addClass("tree-checkbox1");
                    } else {
                        if (isAllNull(node)) {
                            ck.addClass("tree-checkbox0");
                        } else {
                            ck.addClass("tree-checkbox2");
                        }
                    }
                    setParentsChecked($(parentNode.target));
                }
                //是否全选(非级联勾选)
                function isAllSelected(node) {
                  
                    var ck = node.find(".tree-checkbox");
                    //判断当前勾选框的样式状态
                    if (ck.hasClass("tree-checkbox0") || ck.hasClass("tree-checkbox2")) {
                        return false;
                    }
                    var b = true;
                    node.parent().siblings().each(function () {
                        if (!$(this).children("div.tree-node").children(".tree-checkbox").hasClass("tree-checkbox1")) {
                            b = false;
                        }
                    });
                    return b;
                };
                //是否全未勾选
                function isAllNull(node) {
                    var ck = node.find(".tree-checkbox");
                    if (ck.hasClass("tree-checkbox1") || ck.hasClass("tree-checkbox2")) {
                        return false;
                    }
                    var b = true;
                    node.parent().siblings().each(function () {
                        if (!$(this).children("div.tree-node").children(".tree-checkbox").hasClass("tree-checkbox0")) {
                            b = false;
                        }
                    });
                    return b;
                };
            };
        };
        // 设置勾选框的值
        function setCheckBoxValue(jq, target) {
            var options = $.data(jq, "tree").options;
            var node = $(target);
            if (_isLeaf(jq, target)) {//叶子结点
                var ck = node.find(".tree-checkbox");
                if (ck.length) {
                    if (ck.hasClass("tree-checkbox1")) {
                        _check(jq, target, true);
                    } else {
                        _check(jq, target, false);
                    }
                } else {
                    if (options.onlyLeafCheck) {////只显示叶子节点前的复选框
                        $("<span class="tree-checkbox tree-checkbox0"></span>").insertBefore(node.find(".tree-title"));
                    }
                }
            } else {////非叶子结点
                var ck = node.find(".tree-checkbox");
                if (options.onlyLeafCheck) {
                    ck.remove();
                } else {
                    if (ck.hasClass("tree-checkbox1")) {
                        _check(jq, target, true);
                    } else {
                        if (ck.hasClass("tree-checkbox2")) {
                            var checked = true;
                            var unchecked = true;
                            var children = _getChildren(jq, target);
                            for (var i = 0; i < children.length; i++) {
                                if (children[i].checked) {
                                    unchecked = false;
                                } else {
                                    checked = false;
                                }
                            }
                            if (checked) {
                                _check(jq, target, true);
                            }
                            if (unchecked) {
                                _check(jq, target, false);
                            }
                        }
                    }
                }
            }
        };
        //加载树数据
        function _loadData(jq, ul, data, isAppend) {
            var options = $.data(jq, "tree").options;
            data = options.loadFilter.call(jq, data, $(ul).prev("div.tree-node")[0]);
            if (!isAppend) {
                $(ul).empty();
            }
            var checkedNodes = [];
            var depth = $(ul).prev("div.tree-node").find("span.tree-indent, span.tree-hit").length;
            appendNodes(ul, data, depth);
            if (options.dnd) {
                _enableDnd(jq);
            } else {
                _disableDnd(jq);
            }
            for (var i = 0; i < checkedNodes.length; i++) {
                _check(jq, checkedNodes[i], true);
            }
            setTimeout(function () {
                _61(jq, jq);
            }, 0);
            var node = null;
            if (jq != ul) {
                var _5b = $(ul).prev();
                node = _getNode(jq, _5b[0]);
            }
            options.onLoadSuccess.call(jq, node, data);
    
            function appendNodes(ul, children, depth) {
                for (var i = 0; i < children.length; i++) {
                    var li = $("<li></li>").appendTo(ul);
                    var item = children[i];
                    if (item.state != "open" && item.state != "closed") {
                        item.state = "open";
                    }
                    var node = $("<div class="tree-node"></div>").appendTo(li);
                    node.attr("node-id", item.id);
                    $.data(node[0], "tree-node", { id: item.id, text: item.text, iconCls: item.iconCls, attributes: item.attributes });
                    $("<span class="tree-title"></span>").html(item.text).appendTo(node);
                    if (options.checkbox) {
                        if (options.onlyLeafCheck) {
                            if (item.state == "open" && (!item.children || !item.children.length)) {
                                if (item.checked) {
                                    $("<span class="tree-checkbox tree-checkbox1"></span>").prependTo(node);
                                } else {
                                    $("<span class="tree-checkbox tree-checkbox0"></span>").prependTo(node);
                                }
                            }
                        } else {
                            if (item.checked) {
                                $("<span class="tree-checkbox tree-checkbox1"></span>").prependTo(node);
                                checkedNodes.push(node[0]);
                            } else {
                                $("<span class="tree-checkbox tree-checkbox0"></span>").prependTo(node);
                            }
                        }
                    }
                    if (item.children && item.children.length) {
                        var subul = $("<ul></ul>").appendTo(li);
                        if (item.state == "open") {
                            $("<span class="tree-icon tree-folder tree-folder-open"></span>").addClass(item.iconCls).prependTo(node);
                            $("<span class="tree-hit tree-expanded"></span>").prependTo(node);
                        } else {
                            $("<span class="tree-icon tree-folder"></span>").addClass(item.iconCls).prependTo(node);
                            $("<span class="tree-hit tree-collapsed"></span>").prependTo(node);
                            subul.css("display", "none");
                        }
                        appendNodes(subul, item.children, depth + 1);
                    } else {
                        if (item.state == "closed") {
                            $("<span class="tree-icon tree-folder"></span>").addClass(item.iconCls).prependTo(node);
                            $("<span class="tree-hit tree-collapsed"></span>").prependTo(node);
                        } else {
                            $("<span class="tree-icon tree-file"></span>").addClass(item.iconCls).prependTo(node);
                            $("<span class="tree-indent"></span>").prependTo(node);
                        }
                    }
                    for (var j = 0; j < depth; j++) {
                        $("<span class="tree-indent"></span>").prependTo(node);
                    }
                }
            };
        };
        function _61(jq, ul, _63) {
            var options = $.data(jq, "tree").options;
            if (!options.lines) {
                return;
            }
            if (!_63) {
                _63 = true;
                $(jq).find("span.tree-indent").removeClass("tree-line tree-join tree-joinbottom");
                $(jq).find("div.tree-node").removeClass("tree-node-last tree-root-first tree-root-one");
                var _65 = $(jq).tree("getRoots");
                if (_65.length > 1) {
                    $(_65[0].target).addClass("tree-root-first");
                } else {
                    if (_65.length == 1) {
                        $(_65[0].target).addClass("tree-root-one");
                    }
                }
            }
            $(ul).children("li").each(function () {
                var _66 = $(this).children("div.tree-node");
                var ul = _66.next("ul");
                if (ul.length) {
                    if ($(this).next().length) {
                        _67(_66);
                    }
                    _61(jq, ul, _63);
                } else {
                    _68(_66);
                }
            });
            var _69 = $(ul).children("li:last").children("div.tree-node").addClass("tree-node-last");
            _69.children("span.tree-join").removeClass("tree-join").addClass("tree-joinbottom");
            function _68(_6a, _6b) {
                var _6c = _6a.find("span.tree-icon");
                _6c.prev("span.tree-indent").addClass("tree-join");
            };
            function _67(_6d) {
                var _6e = _6d.find("span.tree-indent, span.tree-hit").length;
                _6d.next().find("div.tree-node").each(function () {
                    $(this).children("span:eq(" + (_6e - 1) + ")").addClass("tree-line");
                });
            };
        };
        function request(_70, ul, _71, _72) {
            var _73 = $.data(_70, "tree").options;
            _71 = _71 || {};
            var _74 = null;
            if (_70 != ul) {
                var _75 = $(ul).prev();
                _74 = _getNode(_70, _75[0]);
            }
            if (_73.onBeforeLoad.call(_70, _74, _71) == false) {
                return;
            }
            var _76 = $(ul).prev().children("span.tree-folder");
            _76.addClass("tree-loading");
            var _77 = _73.loader.call(_70, _71, function (_78) {
                _76.removeClass("tree-loading");
                _loadData(_70, ul, _78);
                if (_72) {
                    _72();
                }
            }, function () {
                _76.removeClass("tree-loading");
                _73.onLoadError.apply(_70, arguments);
                if (_72) {
                    _72();
                }
            });
            if (_77 == false) {
                _76.removeClass("tree-loading");
            }
        };
        function expand(_7a, _7b, _7c) {
            var _7d = $.data(_7a, "tree").options;
            var hit = $(_7b).children("span.tree-hit");
            if (hit.length == 0) {
                return;
            }
            if (hit.hasClass("tree-expanded")) {
                return;
            }
            var _7e = _getNode(_7a, _7b);
            if (_7d.onBeforeExpand.call(_7a, _7e) == false) {
                return;
            }
            hit.removeClass("tree-collapsed tree-collapsed-hover").addClass("tree-expanded");
            hit.next().addClass("tree-folder-open");
            var ul = $(_7b).next();
            if (ul.length) {
                if (_7d.animate) {
                    ul.slideDown("normal", function () {
                        _7d.onExpand.call(_7a, _7e);
                        if (_7c) {
                            _7c();
                        }
                    });
                } else {
                    ul.css("display", "block");
                    _7d.onExpand.call(_7a, _7e);
                    if (_7c) {
                        _7c();
                    }
                }
            } else {
                var _7f = $("<ul style="display:none"></ul>").insertAfter(_7b);
                request(_7a, _7f[0], { id: _7e.id }, function () {
                    if (_7f.is(":empty")) {
                        _7f.remove();
                    }
                    if (_7d.animate) {
                        _7f.slideDown("normal", function () {
                            _7d.onExpand.call(_7a, _7e);
                            if (_7c) {
                                _7c();
                            }
                        });
                    } else {
                        _7f.css("display", "block");
                        _7d.onExpand.call(_7a, _7e);
                        if (_7c) {
                            _7c();
                        }
                    }
                });
            }
        };
        function _collapse(_81, _82) {
            var _83 = $.data(_81, "tree").options;
            var hit = $(_82).children("span.tree-hit");
            if (hit.length == 0) {
                return;
            }
            if (hit.hasClass("tree-collapsed")) {
                return;
            }
            var _84 = _getNode(_81, _82);
            if (_83.onBeforeCollapse.call(_81, _84) == false) {
                return;
            }
            hit.removeClass("tree-expanded tree-expanded-hover").addClass("tree-collapsed");
            hit.next().removeClass("tree-folder-open");
            var ul = $(_82).next();
            if (_83.animate) {
                ul.slideUp("normal", function () {
                    _83.onCollapse.call(_81, _84);
                });
            } else {
                ul.css("display", "none");
                _83.onCollapse.call(_81, _84);
            }
        };
        function _toggle(_86, _87) {
            var hit = $(_87).children("span.tree-hit");
            if (hit.length == 0) {
                return;
            }
            if (hit.hasClass("tree-expanded")) {
                _collapse(_86, _87);
            } else {
                expand(_86, _87);
            }
        };
        function _expandAll(_89, _8a) {
            var _8b = _getChildren(_89, _8a);
            if (_8a) {
                _8b.unshift(_getNode(_89, _8a));
            }
            for (var i = 0; i < _8b.length; i++) {
                expand(_89, _8b[i].target);
            }
        };
        function _expandTo(_8d, _8e) {
            var _8f = [];
            var p = _getParent(_8d, _8e);
            while (p) {
                _8f.unshift(p);
                p = _getParent(_8d, p.target);
            }
            for (var i = 0; i < _8f.length; i++) {
                expand(_8d, _8f[i].target);
            }
        };
        function _collapseAll(_92, _93) {
            var _94 = _getChildren(_92, _93);
            if (_93) {
                _94.unshift(_getNode(_92, _93));
            }
            for (var i = 0; i < _94.length; i++) {
                _collapse(_92, _94[i].target);
            }
        };
        // 获取根结点
        function _getRoot(jq) {
            var rootNodes = _getRoots(jq);
            if (rootNodes.length) {
                return rootNodes[0];
            } else {
                return null;
            }
        };
        // 获取所有根结点
        function _getRoots(jq) {
            var roots = [];
            $(jq).children("li").each(function () {
                var nodes = $(this).children("div.tree-node");
                roots.push(_getNode(jq, nodes[0]));
            });
            return roots;
        };
        //获取所有子结点
        function _getChildren(jq, target) {
            var ndoes = [];
            if (target) {
                findChildren($(target));
            } else {
                var rootNodes = _getRoots(jq);
                for (var i = 0; i < rootNodes.length; i++) {
                    ndoes.push(rootNodes[i]);
                    findChildren($(rootNodes[i].target));
                }
            }
            function findChildren(target) {
                target.next().find("div.tree-node").each(function () {
                    ndoes.push(_getNode(jq, this));
                });
            };
            return ndoes;
        };
        //获取父结点
        function _getParent(jq, target) {
            var ul = $(target).parent().parent();
            if (ul[0] == jq) {
                return null;
            } else {
                return _getNode(jq, ul.prev()[0]);
            }
        };
        //获取所有被勾选的结点
        function _getChecked(jq, state) {
            state = state || "checked";
            var stateClass = "";
            if (state == "checked") {
                stateClass = "span.tree-checkbox1";
            } else {
                if (state == "unchecked") {
                    stateClass = "span.tree-checkbox0";
                } else {
                    if (state == "indeterminate") {
                        stateClass = "span.tree-checkbox2";
                    }
                }
            }
            var node = [];
            $(jq).find(stateClass).each(function () {
                var _a9 = $(this).parent();
                node.push(_getNode(jq, _a9[0]));
            });
            return node;
        };
        //获取被选中的结点
        function _getSelected(jq) {
            var nodes = $(jq).find("div.tree-node-selected");
            if (nodes.length) {
                return _getNode(jq, nodes[0]);
            } else {
                return null;
            }
        };
        //追加若干子节点到一个父节点
        function _append(jq, param) {
            var parent = $(param.parent);
            var ul;
            if (parent.length == 0) {
                ul = $(jq);
            } else {
                ul = parent.next();
                if (ul.length == 0) {
                    ul = $("<ul></ul>").insertAfter(parent);
                }
            }
            if (param.data && param.data.length) {
                var icon = parent.find("span.tree-icon");
                if (icon.hasClass("tree-file")) {
                    icon.removeClass("tree-file").addClass("tree-folder tree-folder-open");
                    var hit = $("<span class="tree-hit tree-expanded"></span>").insertBefore(icon);
                    if (hit.prev().length) {
                        hit.prev().remove();
                    }
                }
            }
            _loadData(jq, ul[0], param.data, true);
            setCheckBoxValue(jq, ul.prev());
        };
        //在一个指定节点之前或之后插入节点
        function _insert(jq, target) {
            var ref = target.before || target.after;
            var parentNode = _getParent(jq, ref);
            var li;
            if (parentNode) {
                _append(jq, { parent: parentNode.target, data: [target.data] });
                li = $(parentNode.target).next().children("li:last");
            } else {
                _append(jq, { parent: null, data: [target.data] });
                li = $(jq).children("li:last");
            }
            if (target.before) {
                li.insertBefore($(ref).parent());
            } else {
                li.insertAfter($(ref).parent());
            }
        };
        //删除一个节点和它的子节点
        function _remove(jq, target) {
            var parentNode = _getParent(jq, target);
            var node = $(target);
            var li = node.parent();
            var ul = li.parent();
            li.remove();
            if (ul.children("li").length == 0) {
                var node = ul.prev();
                node.find(".tree-icon").removeClass("tree-folder").addClass("tree-file");
                node.find(".tree-hit").remove();
                $("<span class="tree-indent"></span>").prependTo(node);
                if (ul[0] != jq) {
                    ul.remove();
                }
            }
            if (parentNode) {
                setCheckBoxValue(jq, parentNode.target);
            }
            _61(jq, jq);
        };
        //递归获取某结点数据(包括子结点)  
        function _getData(jq, target) {
            // 获取下一结点的子结点
            function getChildrenOfNextNode(node, ul) {
                ul.children("li").each(function () {
                    var nodes = $(this).children("div.tree-node");
                    var node = _getNode(jq, nodes[0]);
                    var sub = $(this).children("ul");
                    if (sub.length) {
                        node.children = [];
                        getChildrenOfNextNode(node.children, sub);
                    }
                    node.push(node);
                });
            };
            if (target) {
                var node = _getNode(jq, target);
                node.children = [];
                getChildrenOfNextNode(node.children, $(target).next());
                return node;
            } else {
                return null;
            }
        };
        //更新指定的节点
        function _update(jq, param) {
            var target = $(param.target);
            var node = _getNode(jq, param.target);
            if (node.iconCls) {
                target.find(".tree-icon").removeClass(node.iconCls);
            }
            var options = $.extend({}, node, param);
            $.data(param.target, "tree-node", options);
            target.attr("node-id", options.id);
            target.find(".tree-title").html(options.text);
            if (options.iconCls) {
                target.find(".tree-icon").addClass(options.iconCls);
            }
            if (node.checked != options.checked) {
                _check(jq, param.target, options.checked);
            }
        };
        //获取结点
        function _getNode(jq, target) {
            var node = $.extend({}, $.data(target, "tree-node"), { target: target, checked: $(target).find(".tree-checkbox").hasClass("tree-checkbox1") });
            if (!_isLeaf(jq, target)) {
                node.state = $(target).find(".tree-hit").hasClass("tree-expanded") ? "open" : "closed";
            }
            return node;
        };
        //根据ID查找结点
        function _find(jq, id) {
            //
            var nodes = $(jq).find("div.tree-node[node-id=" + id + "]");
            if (nodes.length) {
                return _getNode(jq, nodes[0]);
            } else {
                return null;
            }
        };
        // 选择结点
        function select(jq, target) {
            var options = $.data(jq, "tree").options;
            var node = _getNode(jq, target);
            if (options.onBeforeSelect.call(jq, node) == false) {
                return;
            }
            $("div.tree-node-selected", jq).removeClass("tree-node-selected");
            $(target).addClass("tree-node-selected");
            options.onSelect.call(jq, node);
        };
        //是否叶子结点
        function _isLeaf(jq, target) {
            var node = $(target);
            var hit = node.children("span.tree-hit");
            return hit.length == 0;
        };
        //开始编辑结点
        function _beginEdit(jq, target) {
            var options = $.data(jq, "tree").options;
            var node = _getNode(jq, target);
            if (options.onBeforeEdit.call(jq, node) == false) {
                return;
            }
            $(target).css("position", "relative");
            var nt = $(target).find(".tree-title");
            var outerWidth = nt.outerWidth();
            nt.empty();
            var editor = $("<input class="tree-editor">").appendTo(nt);//编辑器
            editor.val(node.text).focus();
            editor.width(outerWidth + 20);
            editor.height(document.compatMode == "CSS1Compat" ? (18 - (editor.outerHeight() - editor.height())) : 18);
            //设置编辑器事件
            editor.bind("click", function (e) {
                return false;
            }).bind("mousedown", function (e) {
                e.stopPropagation();
            }).bind("mousemove", function (e) {
                e.stopPropagation();
            }).bind("keydown", function (e) {
                if (e.keyCode == 13) {
                    _endEdit(jq, target);
                    return false;
                } else {
                    if (e.keyCode == 27) {
                        _cancelEdit(jq, target);
                        return false;
                    }
                }
            }).bind("blur", function (e) {
                e.stopPropagation();
                _endEdit(jq, target);
            });
        };
        //结束编辑
        function _endEdit(jq, target) {
            var options = $.data(jq, "tree").options;
            $(target).css("position", "");
            var editor = $(target).find("input.tree-editor");
            var val = editor.val();
            editor.remove();
            var node = _getNode(jq, target);
            node.text = val;
            _update(jq, node);
            options.onAfterEdit.call(jq, node);
        };
        // 取消编辑
        function _cancelEdit(jq, target) {
            var options = $.data(jq, "tree").options;
            $(target).css("position", "");
            $(target).find("input.tree-editor").remove();
            var node = _getNode(jq, target);
            _update(jq, node);
            options.onCancelEdit.call(jq, node);
        };
        //实例化树
        $.fn.tree = function (options, param) {
            if (typeof options == "string") {
                return $.fn.tree.methods[options](this, param);
            }
            var options = options || {};
    
            return this.each(function () {
                var data = $.data(this, "tree");
                var options;
                if (data) {
                    options = $.extend(data.options, options);
                    data.options = options;
                } else {
                    options = $.extend({}, $.fn.tree.defaults, $.fn.tree.parseOptions(this), options);
                    $.data(this, "tree", { options: options, tree: wrapTree(this) });
    
                    var jsonData = _getTreeData(this);
                    if (jsonData.length && !options.data) {
                        options.data = jsonData;
                    }
                }
                bindEvent(this);
                if (options.lines) {
                    $(this).addClass("tree-lines");
                }
                if (options.data) {
                    _loadData(this, this, options.data);
                } else {
                    if (options.dnd) {
                        _enableDnd(this);
                    } else {
                        _disableDnd(this);
                    }
                }
                request(this, this);
            });
        };
        //树 方法
        $.fn.tree.methods = {
            //返回树控件属性
            options: function (jq) {
                return $.data(jq[0], "tree").options;
            },
            //读取树控件数据
            loadData: function (jq, data) {
                return jq.each(function () {
                    _loadData(this, this, data);
                });
            },
            //获取指定节点对象 
            getNode: function (jq, target) {
                return _getNode(jq[0], target);
            },
            //获取指定节点数据,包含它的子节点
            getData: function (jq, target) {
                return _getData(jq[0], target);
            },
            //重新载入树控件数据
            reload: function (jq, target) {
                return jq.each(function () {
                    if (target) {
                        var node = $(target);
                        var hit = node.children("span.tree-hit");//获取结点前的展开/折叠对象
                        hit.removeClass("tree-expanded tree-expanded-hover").addClass("tree-collapsed");
                        node.next().remove();//删除子结点
                        expand(this, target);//调用展开方法,重新加载树
                    } else {
                        $(this).empty();
                        request(this, this);
                    }
                });
            },
            //获取根节点,返回节点对象
            getRoot: function (jq) {
                return _getRoot(jq[0]);
            },
            //获取所有根节点,返回节点数组
            getRoots: function (jq) {
                return _getRoots(jq[0]);
            },
            //获取父节点,'target'参数代表节点的DOM对象
            getParent: function (jq, target) {
                return _getParent(jq[0], target);
            },
            //获取所有子节点,'target'参数代表节点的DOM对象
            getChildren: function (jq, target) {
                return _getChildren(jq[0], target);
            },
            //获取所有选中的节点。'state'可用值有:'checked','unchecked','indeterminate'。如果'state'未指定,将返回'checked'节点
            getChecked: function (jq, state) {
                return _getChecked(jq[0], state);
            },
            //获取选择节点并返回它,如果未选择则返回null
            getSelected: function (jq) {
                return _getSelected(jq[0]);
            },
            //判断指定的节点是否是叶子节点,target参数是一个节点DOM对象
            isLeaf: function (jq, target) {
                return _isLeaf(jq[0], target);
            },
            //查找指定节点并返回节点对象
            find: function (jq, id) {
                return _find(jq[0], id);
            },
            //选择一个节点,'target'参数表示节点的DOM对象
            select: function (jq, target) {
                return jq.each(function () {
                    select(this, target);
                });
            },
            //选中指定节点
            check: function (jq, target) {
                return jq.each(function () {
                    _check(this, target, true);
                });
            },
            //取消选中指定节点
            uncheck: function (jq, target) {
                return jq.each(function () {
                    _check(this, target, false);
                });
            },
            //折叠一个节点,'target'参数表示节点的DOM对象
            collapse: function (jq, target) {
                return jq.each(function () {
                    _collapse(this, target);
                });
            },
            //展开一个节点,'target'参数表示节点的DOM对象。在节点关闭或没有子节点的时候,节点ID的值(名为'id'的参数)将会发送给服务器  请求子节点的数据。 
            expand: function (jq, target) {
                return jq.each(function () {
                    expand(this, target);
                });
            },
            //折叠所有节点
            collapseAll: function (jq, target) {
                return jq.each(function () {
                    _collapseAll(this, target);
                });
            },
            //展开所有节点
            expandAll: function (jq, target) {
                return jq.each(function () {
                    _expandAll(this, target);
                });
            },
            //打开从根节点到指定节点之间的所有节点
            expandTo: function (jq, target) {
                return jq.each(function () {
                    _expandTo(this, target);
                });
            },
            //打开或关闭节点的触发器,target参数是一个节点DOM对象
            toggle: function (jq, target) {
                return jq.each(function () {
                    _toggle(this, target);
                });
            },
            //追加若干子节点到一个父节点,param参数有2个属性
            append: function (jq, param) {
                return jq.each(function () {
                    _append(this, param);
                });
            },
            //在一个指定节点之前或之后插入节点,'param'参数包含如下属性:
            //before:DOM对象,在某个节点之前插入。
            //after:DOM对象,在某个节点之后插入。
            //data:对象,节点数据
            insert: function (jq, param) {
                return jq.each(function () {
                    _insert(this, param);
                });
            },
            //移除一个节点和它的子节点,'target'参数是该节点的DOM对象
            remove: function (jq, target) {
                return jq.each(function () {
                    _remove(this, target);
                });
            },
            //移除一个节点和它的子节点,该方法跟remove方法一样,不同的是它将返回被移除的节点数据
            pop: function (jq, target) {
                var node = jq.tree("getData", target);
                jq.tree("remove", target);
                return node;
            },
            //更新指定节点。'param'参数包含以下属性:
            //target(DOM对象,将被更新的目标节点),id,text,iconCls,checked等
            update: function (jq, target) {
                return jq.each(function () {
                    _update(this, target);
                });
            },
            //启用拖拽功能
            enableDnd: function (jq) {
                return jq.each(function () {
                    _enableDnd(this);
                });
            },
            //禁用拖拽功能
            disableDnd: function (jq) {
                return jq.each(function () {
                    _disableDnd(this);
                });
            },
            //开始编辑一个节点
            beginEdit: function (jq, target) {
                return jq.each(function () {
                    _beginEdit(this, target);
                });
            },
            //结束编辑一个节点
            endEdit: function (jq, target) {
                return jq.each(function () {
                    _endEdit(this, target);
                });
            },
            //取消编辑一个节点
            cancelEdit: function (jq, target) {
                return jq.each(function () {
                    _cancelEdit(this, target);
                });
            }
        };
        //解析器
        $.fn.tree.parseOptions = function (target) {
            var t = $(target);
            return $.extend({},
                $.parser.parseOptions(target, ["url", "method", { checkbox: "boolean", cascadeCheck: "boolean", onlyLeafCheck: "boolean" },
                    { animate: "boolean", lines: "boolean", dnd: "boolean" }]));
        };
        //树-默认属性+事件
        $.fn.tree.defaults = {
            url: null,//检索远程数据的URL地址
            method: "post",//检索数据的HTTP方法。(POST / GET)
            animate: false,//定义节点在展开或折叠的时候是否显示动画效果
            checkbox: false,//定义是否在每一个借点之前都显示复选框
            cascadeCheck: true,//定义是否层叠选中状态
            onlyLeafCheck: false,//定义是否只在末级节点之前显示复选框
            lines: false,//定义是否显示树控件上的虚线
            dnd: false,//定义是否启用拖拽功能
            data: null,//节点数据加载
            //定义如何从远程服务器加载数据。返回false可以忽略本操作
            loader: function (param, _success, _error) {
                var opts = $(this).tree("options");
                if (!opts.url) {
                    return false;
                }
                $.ajax({
                    type: opts.method,
                    url: opts.url,
                    data: param,
                    dataType: "json",
                    success: function (data) {
                        _success(data);
                    },
                    error: function () {
                        _error.apply(this, arguments);
                    }
                });
            },
            //返回过滤过的数据进行展示。返回数据是标准树格式
            loadFilter: function (data, parent) {
                return data;
            },
            //事件--
            //在请求加载远程数据之前触发,返回false可以取消加载操作
            onBeforeLoad: function (node, param) {
            },
            //在数据加载成功以后触发
            onLoadSuccess: function (node, data) {
            },
            //在数据加载失败的时候触发,arguments参数和jQuery的$.ajax()函数里面的'error'回调函数的参数相同
            onLoadError: function () {
            },
            //在用户点击一个节点的时候触发
            onClick: function (node) {
            },
            //在用户双击一个节点的时候触发
            onDblClick: function (node) {
            },
            //在节点展开之前触发,返回false可以取消展开操作
            onBeforeExpand: function (node) {
            },
            //在节点展开的时候触发
            onExpand: function (node) {
            },
            //在节点折叠之前触发,返回false可以取消折叠操作
            onBeforeCollapse: function (node) {
            },
            //在节点折叠的时候触发
            onCollapse: function (node) {
            },
            //在用户点击勾选复选框之前触发,返回false可以取消选择动作
            onBeforeCheck: function (node, checked) {
            },
            //在用户点击勾选复选框的时候触发
            onCheck: function (node, checked) {
            },
            //在用户选择一个节点之前触发,返回false可以取消选择动作
            onBeforeSelect: function (node) {
            },
            //在用户选择节点的时候触发
            onSelect: function (node) {
            },
            //在右键点击节点的时候触发
            onContextMenu: function (e, node) {
            },
            //在开始拖动节点之前触发,返回false可以拒绝拖动
            onBeforeDrag: function (node) {
            },
            //在开始拖动节点的时候触发
            onStartDrag: function (node) {
            },
            //在停止拖动节点的时候触发
            onStopDrag: function (node) {
            },
            //在拖动一个节点进入到某个目标节点并释放的时候触发,返回false可以拒绝拖动
            onDragEnter: function (target, source) {
            },
            //在拖动一个节点经过某个目标节点并释放的时候触发,返回false可以拒绝拖动
            onDragOver: function (target, source) {
            },
            //在拖动一个节点离开某个目标节点并释放的时候触发,返回false可以拒绝拖动
            onDragLeave: function (target, source) {
            },
            //当节点位置被拖动时触发
            onDrop: function (target, source, point) {
            },
            //在编辑节点之前触发
            onBeforeEdit: function (node) {
            },
            //在编辑节点之后触发
            onAfterEdit: function (node) {
            },
            //在取消编辑操作的时候触发
            onCancelEdit: function (node) {
            }
        };
    })(jQuery);
    View Code

    示例代码

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title>Basic Tree - jQuery EasyUI Demo</title>
        <link rel="stylesheet" type="text/css" href="../../themes/default/easyui.css">
        <link rel="stylesheet" type="text/css" href="../../themes/icon.css">
        <link rel="stylesheet" type="text/css" href="../demo.css">
        <script type="text/javascript" src="../../jquery-1.8.0.min.js"></script>
        <script src="../../plugins2/jquery.parser.js"></script>
        <script src="../../plugins2/jquery.draggable.js"></script>
        <script src="../../plugins2/jquery.droppable.js"></script>
        <script src="../../plugins2/jquery.tree.js"></script>
    </head>
    <body>
        <h2>Basic Tree</h2>
        <div class="demo-info">
            <div class="demo-tip icon-tip"></div>
            <div>Click the arrow on the left to expand or collapse nodes.</div>
        </div>
        <div style="margin:10px 0;"></div>
        <ul class="easyui-tree">
            <li>
                <span>My Documents</span>
                <ul>
                    <li data-options="state:'closed'">
                        <span>Photos</span>
                        <ul>
                            <li>
                                <span>Friend</span>
                            </li>
                            <li>
                                <span>Wife</span>
                            </li>
                            <li>
                                <span>Company</span>
                            </li>
                        </ul>
                    </li>
                    <li>
                        <span>Program Files</span>
                        <ul>
                            <li>Intel</li>
                            <li>Java</li>
                            <li>Microsoft Office</li>
                            <li>Games</li>
                        </ul>
                    </li>
                    <li>index.html</li>
                    <li>about.html</li>
                    <li>welcome.html</li>
                </ul>
            </li>
        </ul>
    
    </body>
    </html>
    View Code

    插件效果

    热爱编程,热爱技术,热爱生活
  • 相关阅读:
    四轴PID思路整理
    STM32输入捕获TIM2四通道
    四轴和遥控器的对应
    四层板学习(二)
    四层板学习(一)布线前的准备
    冲突的处理方法
    散列表
    重设置电脑时间
    深圳销量统计源码分析
    源码分析
  • 原文地址:https://www.cnblogs.com/DemoLee/p/3501103.html
Copyright © 2020-2023  润新知