zoukankan      html  css  js  c++  java
  • jQuery第六课:实现一个Ajax的TreeView

    TreeView是asp.net自带的控件,不过自带的控件在灵活性上有诸多限制。在jQuery的帮助下,自己实现一个TreeView也不困难。本文是前几篇文章所讲内容的一个综合演练。最终实现的效果是一个目录文件查看器,如图所示:

    image

    其原理是,当用户单击一个目录的时候,将这个目录的路径发送给服务器端,服务器端返回这个目录中的文件和目录信息。在服务器端,定义一个如下的类来表示要传递的文件信息:

    public class FileInformation
    {
        public string FullPath
        {
            get;        set;
        }
        public string Name
        {
            get;        set;
        }
        public string Info
        {
            get;        set;
        }
        public bool IsFolder
        {
            get;        set;
        }
    }

    其中FullPath是文件的完整路径,用于获取它的子文件夹/文件用,Name是文件的名字,用于显示,IsFolder是区分这条数据是一个文件还是文件夹,以便用不同的图标来显示,最后一个Info是一些附加信息,在此例中没有用到。根据一个路径获得目录中的文件信息的C#代码很简单,顺便就贴在这里:

    public class FileManager
    {
        public static List<FileInformation> GetFolderContent(string fullpath)
        {
            List<FileInformation> res = new List<FileInformation>();
            DirectoryInfo info = new DirectoryInfo(fullpath);
            if (info.Exists)
            {           
                foreach (DirectoryInfo d in info.GetDirectories())
                {
                    res.Add(new FileInformation
                    {
                        FullPath = d.FullName, Name = d.Name,IsFolder = true,
                        Info = "Any More Information goes here"
                    });
                }
                foreach (FileInfo f in info.GetFiles())
                {
                    res.Add(new FileInformation
                    {
                        FullPath = f.FullName,Name = f.Name,IsFolder = false,
                        Info = "Any More Information goes here"
                    });
                }
            }
            return res;
        }
    }

    此例中采用JSON数据的格式来传递这些信息。因此要将这些数据序列化。在.Net 3.5中,有现成的将实体类序列化成JSON数据的类,使用方法如下

    public static string ToJson<T>(T obj)
        {
            DataContractJsonSerializer d = new DataContractJsonSerializer(typeof(T));
            System.IO.MemoryStream ms = new System.IO.MemoryStream();
            d.WriteObject(ms, obj);
            string strJSON = System.Text.Encoding.UTF8.GetString(ms.ToArray());
            ms.Close();
            return strJSON;
        }

    如果是.net 2.0,则可以寻找一些第三方的组件,自己写一个也不麻烦。

    至此,服务器端的主要工作已经完成了。新建一个Genric Handler文件,filelist.ashx,代码如下,简单的响应下请求,输出数据即可:

    public class FileList : IHttpHandler {    
        public void ProcessRequest (HttpContext context) {
            string path = context.Request.QueryString["path"];
            string data = JsonHelper.ToJson<List<FileInformation>>(FileManager.GetFolderContent(path));
            context.Response.Write(data);
        } 
        public bool IsReusable {
            get {
                return false;
            }
        }
    }

    下面考虑客户端html代码的编写。最主要的就是两个事件,也就是鼠标点击发送ajax请求,处理返回的json数据生成html代码,鼠标再次点击将html代码清空。在这里,采用ul li来显示这个treeview,在li中有一个不可见的span,里面包含了文件完整的路径,它将用作发起ajax请求的参数,但是对用户是不可见的。

    HTML代码很简单,就4行:

    <body>
    <ul>
    </ul>
    </body>

    首先需要初始化一个根目录,例如D:,代码如下:

    $(function() {
                $('<li class="folder">D:\\<span class="fullpath">D:\\</span></li>').appendTo('ul');
    
                $('li').hover(function() {
                    $(this).css('cursor', 'pointer');
                },
                    function() { $(this).css('cursor', 'default'); });
    
                $('li.folder').toggle(LoadFile, CloseFolder);
            });

    构造好一个li结点,添加到ul中去,然后设置下鼠标动作的样式,最后为其绑定事件处理程序,LoadFile和CloseFolder。

    function LoadFile(event) {
                if (this == event.target) {
                    var path = $(this).find('span').html();
                    var node = $('<ul>');
                    $(this).append(node);
                    $.getJSON('filelist.ashx', { path: path }, function(data) {
                        $.each(data, function() {
                            if (this.IsFolder) {
                                node.append($('<li>').addClass('folder').html(this.Name).append($('<span>').addClass('fullpath').html(this.FullPath)));
                            }
                            else {
                                node.append($('<li>').addClass('file').html(this.Name).append($('<span>').addClass('fullpath').html(this.FullPath)));
                            }
                        });
                        node.find('li.folder').toggle(LoadFile, CloseFolder);
                    });                 
                }
            }

    首先要判断event的target和this是否是同一个对象,以避免点击子节点事件浮升的时候造成多次触发。首先利用find和html函数获得完整的路径。构造好一个ul节点并把它添加到当前的li中。此时ul是空的,接下来发起ajax请求,获得服务器端的数据。对每条数据生成一个li,其中对于是否是目录加以判断,生成带有不同class的li,再加到node中。最后,不要忘记为新增的节点也绑定事件处理程序。代码还是比较简单的,至于关闭目录节点的代码就更加简单了,

    function CloseFolder(event) {
        if (this == event.target)
            $(this).find('ul').remove();
    }

    至此此范例已经完成了。还少了几句css,不再列出。

    这个例子实现的功能和样式都比较粗糙,不过在此基础上做更多的扩展和美化已经不是难事。例如可以加上一点现成的动画效果:

    function CloseFolder(event) {
        if (this == event.target) {
            var node = $(this).find('ul');
            node.hide('slow', function() { $(this).find('ul').remove(); });                
        }
    }
    先隐藏,再删除。类似地,可以加载完毕后立刻隐藏,再淡出。
  • 相关阅读:
    Jquery 操作radio实例
    不错的linux下通用的java程序启动脚本(转载)
    activeMQ消费消息时网络流量异常大的问题
    利用passssh,批量远程修改机器密码
    tomcat的maxThreads、acceptCount(最大线程数、最大排队数)
    非阻塞IO、NIO为什么会快,我们为什么需要多线程
    关于find命令 name 匹配字符无法正确生效的问题 find: paths must precede expression:
    想取得刚才nextval()的值时,放心大胆的用currval()吧,currval()的返回值并不会因为nextval()的并发访问而混乱
    slef4j的好处
    杂(一) 奶酪
  • 原文地址:https://www.cnblogs.com/yinzixin/p/1730515.html
Copyright © 2011-2022 走看看