extaspnet:ExtAspNet应用窍门技巧( 2十 2) - Ext4JSLint的JSON文件创建树Control控件来源: 发布时间:星期五, 2009年9月25日 浏览:3次 评论:0
引子 Ext4JSLint是使用ExtAspNet来展示JSLint-Toolkit检查结果的开源项目。 JSLint-Toolkit是一个使用Rhino和JSLint的开源项目,可以对一个文件夹中的所有JavaScript进行语法检查,并显示友好的检查结果。 下面是JSLint-Toolkit生成的检查结果: [{ "name": "source", "type": "folder", "kids": [ { "name": "config.js", "type": "file", "errors": [0, 0, 0] }, { "name": "lint.js", "type": "file", "errors": [3, 0, 3] }, { "name": "main.js", "type": "file", "errors": [0, 0, 0] }, { "name": "util.js", "type": "file", "errors": [0, 0, 0] } ], "basePath": "scripts/source", "fileCount": 4, "errors": [3, 0, 3] }, { "name": "jquery-1.3.2.js", "type": "file", "basePath": "scripts/jquery-1.3.2.js", "errors": [51, 43, 8] }] 这样一个JSON字符串其实描述了一个如下的文件结构: +scripts/source -config.js -lint.js -main.js -util.js -scripts/jquery-1.3.2.js 特别注意的是,根节点多了一个属性basePath用来表示根路径。 errors表示此JavaScript文件中的错误数(这是一个数组,第一个表示总数,第二个表示严重错误的个数)。 页面效果: ASPX标签定义 <ext:Tree runat="server" ID="Tree1" ShowBorder="false" ShowHeader="false" AutoScroll="true" EnableArrows="true" OnNodeCommand="Tree1_NodeCommand"> </ext:Tree> 标签定义非常简单,因为所有的逻辑都在后台实现了。 同时定义了点击树节点的事件处理OnNodeCommand="Tree1_NodeCommand",因为我们要在点击树节点时更新中间的Grid,也即是当前JavaScript的错误列表。 树与递归 只要有树的地方就少不了递归函数,因此这段代码对于我们理解递归也很有帮助。 首先看看页面初始化代码: protected void Page_Load(object sender, EventArgs e) { if (!IsPostBack) { LoadData(true); } } #region LoadData private void LoadData(bool showAllErrors) { btnExpandAll.OnClientClick = Tree1.GetExpandAllNodesReference(); btnCollapseAll.OnClientClick = Tree1.GetCollapseAllNodesReference(); string treestr = GetFileContent("~/data/json/tree.json"); List<string> treePathList = new List<string>(); ResolveMenuTree(new JSONArray(treestr), treePathList, showAllErrors, Tree1.Nodes); } private string GetFileContent(string path) { string treestr = String.Empty; using (StreamReader sr = new StreamReader(Server.MapPath(path))) { treestr = sr.ReadToEnd(); } return treestr; } private void ResolveMenuTree(JSONArray ja, List<string> treePathList, bool showAllErrors, ExtAspNet.TreeNodeCollection nodes) { // TODO 递归生成树 } private string GetTreePath(List<string> treePath) { string path = String.Empty; foreach (string node in treePath) { path += node + "/"; } return path.TrimEnd('/'); } 我们通过Nii.JSON这个开源类库(已经包含在ExtAspNet中),来将JSON字符串转换为JSONArray对象,以便在递归中使用: JSONArray ja = new JSONArray(treestr); 递归生成树 为了让大家看清问题的本质,我首先放出一个简单的递归,只完成基本功能: private void ResolveMenuTree2(JSONArray ja, List<string> treePathList, bool showAllErrors, ExtAspNet.TreeNodeCollection nodes) { for (int i = 0; i < ja.Count; i++) { JSONObject kid = ja[i] as JSONObject; string name = kid.getString("name"); // 当前路径,如果basePath存在说明是根目录 if (kid.has("basePath")) { treePathList.Add(kid.getString("basePath")); } else { treePathList.Add(name); } string currentPath = GetTreePath(treePathList); string type = kid.getString("type"); // 如果文件夹中没有文件,则不添加此文件夹 if (type == "folder" && kid.getInt("fileCount") == 0) { treePathList.RemoveAt(treePathList.Count - 1); continue; } ExtAspNet.TreeNode node = new ExtAspNet.TreeNode(); nodes.Add(node); node.Text = name; node.Text = String.Format("<span qtip=\"{0}\">{1}</span>", currentPath, node.Text); if (type == "folder") { node.SingleClickExpand = true; ResolveMenuTree2(kid.getJSONArray("kids"), treePathList, showAllErrors, node.Nodes); } else { node.Leaf = true; } treePathList.RemoveAt(treePathList.Count - 1); } } 在这段代码中,我们通过treePathList来记录当前节点的路径,这也是一个关键点。 此时生成的页面截图: 完整的代码(根据错误设置节点颜色,同时为有错误的节点可回发): private void ResolveMenuTree(JSONArray ja, List<string> treePathList, bool showAllErrors, ExtAspNet.TreeNodeCollection nodes) { for (int i = 0; i < ja.Count; i++) { JSONObject kid = ja[i] as JSONObject; string name = kid.getString("name"); // 当前路径,如果basePath存在说明是根目录 if (kid.has("basePath")) { treePathList.Add(kid.getString("basePath")); } else { treePathList.Add(name); } string currentPath = GetTreePath(treePathList); // 获取JSLint错误数 JSONArray errors = kid.getJSONArray("errors"); int errorCount = errors.getInt(0); int criticalErrorCount = errors.getInt(1); if (showAllErrors) { if (errorCount > 0) { name += String.Format(" ({0})", errorCount); } } else { if (criticalErrorCount > 0) { name += String.Format(" ({0})", criticalErrorCount); } } string type = kid.getString("type"); // 如果文件夹中没有文件,则不添加此文件夹 if (type == "folder" && kid.getInt("fileCount") == 0) { treePathList.RemoveAt(treePathList.Count - 1); continue; } ExtAspNet.TreeNode node = new ExtAspNet.TreeNode(); nodes.Add(node); node.Text = name; //node.ToolTip = currentPath; // 节点的显示颜色 string style = ""; if (showAllErrors) { if (errorCount == 0) { style = "color:green;"; } else { if (criticalErrorCount == 0) { style = "color:#FF9900;"; } else { style = "color:#FF0000;"; } } } else { if (criticalErrorCount != 0) { style = "color:#FF0000;"; } else { style = "color:green;"; } } node.Text = String.Format("<span qtip=\"{2}\" style=\"{0}\">{1}</span>", style, node.Text, currentPath); if (type == "folder") { node.SingleClickExpand = true; ResolveMenuTree(kid.getJSONArray("kids"), treePathList, showAllErrors, node.Nodes); } else { node.Leaf = true; if (showAllErrors) { if (errorCount != 0) { node.EnablePostBack = true; node.CommandName = currentPath; } } else { if (criticalErrorCount != 0) { node.EnablePostBack = true; node.CommandName = currentPath; } } } treePathList.RemoveAt(treePathList.Count - 1); } } 下一章将讲述如何点击左侧树节点时更新中间的Grid控件,并加载右侧的IFrame(即JavaScript文件的内容)。 下载全部源代码 0
相关文章
读者评论发表评论 |