1

我已经为此倾注了好几个小时,但我还没有取得很大进展,所以我希望 SO 的一位出色的居民可以帮助我。这就是问题所在...

我正在通过 jQuery 的 jstree 插件实现一棵树。我正在通过 json 从我们的 web 应用程序中以编程方式填充树的数据提取到一个 asp:HiddenField 中,基本上像这样:

JavaScriptSerializer serializer = new JavaScriptSerializer();
string json = serializer.Serialize(Items);

json = json.ToLower();
data.Value = json;    

然后,树从隐藏字段中提取 json 来构建自己。在我尝试为选择/打开的节点保留数据之前,这工作得非常好。为了简化我的问题,我将一些 json 数据硬编码到树中,并尝试使用 cookie 插件来保存树状态数据。无论出于何种原因,这都不起作用。我已经看到人们需要按特定顺序加载插件等的其他问题,这并没有解决我的问题。我用 html_data 尝试了相同的设置,并且效果很好。通过这种工作持久性,我转换了 cookie 插件以将数据持久保存在不同的 asp:hiddenfield 中(我们不能在我们的应用程序中将 cookie 用于这种类型的东西。)

本质上 cookie 操作是相同的,它只是将节点数组保存为隐藏字段的值。这适用于 html_data,但仍然不适用于 json,而且我还不能确定它失败的地方。

这是 jQuery.cookie.js 替换:

jQuery.persist = function(name, value) {
    if (typeof value != 'undefined') { // name and value given, set persist
        if (value === null) {
            value = '';
        }
        jQuery('#' + name).attr('value', value);
    } else { // only name given, get value
        var persistValue = null;
        persistValue = jQuery('#' + name).attr('value');
        return persistValue;
    }
};

jstree.cookie.js 代码是相同的,除了一些变量名更改。这是我的树:

$(function() {
                $("#demo1").jstree({
                    "json_data": {
                        "data" : [
                        {
                            "data" : "A node",
                            "children" : [ "Child 1", "Child 2" ]
                        },
                        {
                            "attr": { "id": "li.node.id" },
                            "data" : {
                                "title": "li.node.id",
                                "attr": { "href": "#" }
                            },
                            "children": ["Child 1", "Child 2"]
                        }
                    ]
                    },
                    "persistence": {
                        "save_opened": "<%= open.ClientID %>",
                        "save_selected": "<%= select.ClientID %>",
                        "auto_save": true
                    },
                   "plugins": ["themes", "ui", "persistence", "json_data"]
                });
            });

数据 - 被适当地存储在隐藏字段中,问题发生在回发时,它不会重新打开节点。任何帮助将不胜感激。

再看一遍之后,我只是想解释一下,在我看来,问题是在尝试持久性操作时,还没有从 JSON_data 构建树。有没有办法将这些操作推迟到树完全加载之后?

4

2 回答 2

2

如果有人仍在尝试在 jsTree 3.0+ 版本上执行相同类型的操作,那么有一种更简单的方法可以完成相同类型的功能,无需编辑任何 jsTree 的核心 JavaScript,也无需依赖“状态”插件(版本 1.0 - “持久性”):

var jsTreeControl = $("#jsTreeControl");
//Can be a "asp:HiddenField"
var stateJSONControl = $("#stateJSONControl");
var url = "exampleURL";

jsTreeControl.jstree({
    'core': {
        "data": function (node, cb) {
            var thisVar = this;

            //On the initial load, if the "state" already exists in the hidden value 
            //then simply use that rather than make a AJAX call
            if (stateJSONControl.val() !== "" && node.id === "#") {
                cb.call(thisVar, { d: JSON.parse(stateJSONControl.val()) });
            }
            else {
                $.ajax({
                    type: "POST",
                    url: url,
                    async: true,
                    success: function (json) {
                        cb.call(thisVar, json);
                    },
                    contentType: "application/json; charset=utf-8",
                    dataType: "json"
                }).responseText;
            }
        }
    }
});

//If the user changes the jsTree, save the full JSON of the jsTree into the hidden value, 
//this will then be restored on postback by the "data" function in the jsTree decleration
jsTreeControl.on("changed.jstree", function (e, data) {
    if (typeof (data.node) != 'undefined') {
        stateJSONControl.val(JSON.stringify(jsTreeControl.jstree(true).get_json()));
    }
});

此代码将创建一个 jsTree 并将其“状态”保存到隐藏值中,然后在重新创建 jsTree 时回发时,它将使用从“隐藏字段”恢复的旧“状态”,而不是进行新的 AJAX 调用并丢失用户所做的扩展/选择。

于 2016-02-26T20:02:53.220 回答
1

让它与 JSON 数据一起正常工作。我不得不在 jstree 内部编辑“重新打开”和“重新选择”功能。

这是任何需要它的人的新功能重新打开功能。

reopen: function(is_callback) {
                var _this = this,
                    done = true,
                    current = [],
                    remaining = [];
                if (!is_callback) { this.data.core.reopen = false; this.data.core.refreshing = true; }
                if (this.data.core.to_open.length) {
                    $.each(this.data.core.to_open, function(i, val) {
                        val = val.replace(/^#/, "")
                        if (val == "#") { return true; }
                        if ($(("li[id=" + val + "]")).length && $(("li[id=" + val + "]")).is(".jstree-closed")) { current.push($(("li[id=" + val + "]"))); }
                        else { remaining.push(val); }
                    });
                    if (current.length) {
                        this.data.core.to_open = remaining;
                        $.each(current, function(i, val) {
                            _this.open_node(val, function() { _this.reopen(true); }, true);
                        });
                        done = false;
                    }
                }
                if (done) {
                    // TODO: find a more elegant approach to syncronizing returning requests
                    if (this.data.core.reopen) { clearTimeout(this.data.core.reopen); }
                    this.data.core.reopen = setTimeout(function() { _this.__callback({}, _this); }, 50);
                    this.data.core.refreshing = false;
                }
            },

问题是它试图找到

  • 自定义属性的元素。它只是将这些字符串推入数组以在需要节点对象时进行搜索。使用这条线

    if ($(("li[id=" + val + "]")).length && $(("li[id=" + val + "]")).is(".jstree-closed")) { current.push($(("li[id=" + val + "]"))); }
    

    代替

    if ($(val).length && $(val).is(".jstree-closed")) { current.push(val); }
    

    就是这样。使用类似的过程,我也能够以这种方式持久化选定的节点。

    希望这对某人有帮助。

  • 于 2010-09-03T19:03:08.640 回答