jQuery Tree(pioz):使用cookie无法正确呈现树

时间:2011-04-03 22:28:28

标签: jquery treeview tree

我正在使用这里的jQuery树https://github.com/pioz/jquery-tree#readme

问题是当我进行cookie保存时渲染树。当需要重新渲染它时,如果我不遵循特定的方式放置有序列表,代码就无法正常工作。

我想最好看看我提出的这个演示代码。

http://jsbin.com/emaku4/23

  1. 整棵树都打开了
  2. 点击第3级箭头展开(对于两棵树)
  3. 刷新
  4. 现在,第一棵树再次正确呈现,其中cookie显示之前打开的内容,但第二棵树没有。我认为这是因为在第二个问题上,我把没有分层的那个放在带有子级的那个上面(这个叫做“这就是差异”)。

    有没有办法调整代码,这样无论我在任何子级别中有什么顺序,它都可以使用cookie正确呈现视图?

    // Require jQuery
    // Use jQuery.cookie if you want to restore the previous expansion of the tree
    
    jQuery.fn.tree = function(options) {
    
      // Setup default options
      /** Avaiable options are:
       *  - open_char: defeault character to display on open node in tree
       *  - close_char: defeault character to display on close node in tree
       *  - default_expanded_paths_string: if no cookie found the tree will be expand with this paths string
      **/
      if(options === undefined || options === null)
        options = {};
      var open_char = options.open_char;
      var close_char = options.close_char;
      var default_expanded_paths_string = options.default_expanded_paths_string;
      if(open_char === undefined || open_char === null)
        open_char = '▼';
      if(close_char === undefined || close_char === null)
        close_char = '►';
      if(default_expanded_paths_string === undefined || default_expanded_paths_string === null)
        default_expanded_paths_string = '0';
    
      // Get the expanded paths from the current state of tree
      jQuery.fn.save_paths = function() {
        var paths = [];
        var path = [];
        var open_nodes = jQuery(this).find('li span.open');
        var last_depth = null;
        for(var i = 0; i < open_nodes.length; i++) {
          var depth = jQuery(open_nodes[i]).parents('ul').length-1;
          if((last_depth == null && depth > 0) || (depth > last_depth && depth-last_depth > 1))
            continue;
          var pos = jQuery(open_nodes[i]).parent().prevAll().length;
          if(last_depth == null) {
            path = [pos];
          } else if(depth < last_depth) {
            paths.push(path.join('/'));
            var diff = last_depth - depth;
            path.splice(path.length-diff-1, diff+1);
            path.push(pos);
          } else if(depth == last_depth) {
            paths.push(path.join('/'));
            path.splice(path.length-1, 1);
            path.push(pos);
          } else if(depth > last_depth) {
            path.push(pos);
          }
          last_depth = depth;
        }
        paths.push(path.join('/'));
        try { jQuery.cookie(this.attr('class'), paths.join(',')); }
        catch(e) {}
      };
    
      // This function expand the tree with 'path'
      jQuery.fn.restore_paths = function() {
        var paths_string = null;
        try { paths_string = jQuery.cookie(this.attr('class')); }
        catch(e) { paths_string = default_expanded_paths_string; }
        if(paths_string === null || paths_string === undefined)
          paths_string = default_expanded_paths_string;
        var paths = paths_string.split(',');
        for(var i = 0; i < paths.length; i++) {
          var obj = jQuery(this);
          var path = paths[i].split('/');
          for(var j = 0; j < path.length; j++) {
            obj = jQuery(obj.children('li').children('ul')[path[j]]);
            obj.show();
            obj.parent().children('span').attr('class', 'open');
            obj.parent().children('span').html(open_char);
          }
        }
      };
    
      for(var i = 0; i < this.length; i++) {
        if(this[i].tagName === 'UL') {
          // Make a tree
          jQuery(this[i]).find('li').has('ul').prepend('<span class="close" style="cursor:pointer;">' + close_char + '</span>');
          jQuery(this[i]).find('ul').hide();
          // Restore cookie expand path
          jQuery(this[i]).restore_paths();
          // Click event
          jQuery(this[i]).find('span').live('click', {tree : this[i]}, function(e) {
            if (jQuery(this).attr('class') == 'open') {
              jQuery(this).parent().children('ul').hide('slow');
              jQuery(this).attr('class', 'close');
              jQuery(this).html(close_char);
            } else if (jQuery(this).attr('class') == 'close') {
              jQuery(this).parent().children('ul').show('slow');
              jQuery(this).attr('class', 'open');
              jQuery(this).html(open_char);
            }
            jQuery(e.data.tree).save_paths();
          });
        }
      }
    }
    

2 个答案:

答案 0 :(得分:2)

问题出在jquery.tree.js的line 34中(jQuery.fn.save_paths()内):

var pos = jQuery(open_nodes[i]).parent().prevAll().length;

open_nodes[i]是开放/关闭span,其父级是li,因此prevAll()计算前一个li的数量。

但在line 68jQuery.fn.restore_paths()内)中进一步向下:

obj = jQuery(obj.children('li').children('ul')[path[j]]);

它使用save_paths()中保存的位置来查找第n个ul

因此,在您的情况下,在展开第一个(仅限)ul之后,save_paths()会记住1(因为li之前有ul }),但是当您重新加载页面时,restore_paths()尝试展开“第二个”ul(第一个是0,第二个ul1 )。

嗯,我不认为我解释得很好......


无论如何,解决方案是改变第34​​行:

var pos = jQuery(open_nodes[i]).parent().prevAll().length;

到此:

var pos = jQuery(open_nodes[i]).parent().prevAll(':has(">ul")').length;

这将确保在计算当前li的位置时跳过没有嵌套ul的{​​{1}}。


我已经通过此修复程序向pioz提交了拉取请求。在此期间,您可以使用我的fork中的固定版本:https://github.com/jefferyto/jquery-tree/raw/counting-fix/jquery.tree.js

您可以在此处看到它:http://jsbin.com/emaku4/28

更新: pioz提交了(不同的)修复程序。您可以在https://github.com/pioz/jquery-tree下载工作代码。谢谢pioz!

答案 1 :(得分:1)

看看这个:http://docs.jquery.com/Plugins/Treeview/treeview

为cookie设置persist选项,如下所示:

$(".selector").treeview({
    persist: "cookie"
});

这是一种渲染树视图的简便方法。