原创|其它|编辑:郝浩|2009-09-24 09:38:14.000|阅读 1197 次
概述:Ext4JSLint是使用ExtAspNet来展示JSLint-Toolkit检查结果的开源项目。 JSLint-Toolkit是一个使用Rhino和JSLint的开源项目,可以对一个文件夹中的所有JavaScript进行语法检查,并显示友好的检查结果。
# 界面/图表报表/文档/IDE等千款热门软控件火热销售中 >>
引子 
Ext4JSLint是使用来展示JSLint-Toolkit检查结果的开源项目。 
是一个使用Rhino和JSLint的开源项目,可以对一个文件夹中的所有JavaScript进行语法检查,并显示友好的检查结果。 
下面是JSLint-Toolkit生成的检查结果:
01.[{ 02.    "name": "source",  03.    "type": "folder",  04.    "kids": [ 05.     { 06.      "name": "config.js",  07.      "type": "file",  08.      "errors": [0, 0, 0] 09.     },  10.     { 11.      "name": "lint.js",  12.      "type": "file",  13.      "errors": [3, 0, 3] 14.     },  15.     { 16.      "name": "main.js",  17.      "type": "file",  18.      "errors": [0, 0, 0] 19.     },  20.     { 21.      "name": "util.js",  22.      "type": "file",  23.      "errors": [0, 0, 0] 24.     } 25.    ],  26.    "basePath": "scripts/source",  27.    "fileCount": 4,  28.    "errors": [3, 0, 3] 29.},  30.{ 31.    "name": "jquery-1.3.2.js",  32.    "type": "file",  33.    "basePath": "scripts/jquery-1.3.2.js",  34.    "errors": [51, 43, 8] 35.}] 
这样一个JSON字符串其实描述了一个如下的文件结构:
+scripts/source
     -config.js
     -lint.js
     -main.js
     -util.js
    -scripts/jquery-1.3.2.js
特别注意的是,根节点多了一个属性basePath用来表示根路径。 
errors表示此JavaScript文件中的错误数(这是一个数组,第一个表示总数,第二个表示严重错误的个数)。 
页面效果: 
 
ASPX标签定义
1.<ext:Tree runat="server" ID="Tree1" ShowBorder="false" ShowHeader="false" AutoScroll="true"2.    EnableArrows="true" OnNodeCommand="Tree1_NodeCommand"> 3.</ext:Tree> 
标签定义非常简单,因为所有的逻辑都在后台实现了。 
同时定义了点击树节点的事件处理OnNodeCommand="Tree1_NodeCommand",因为我们要在点击树节点时更新中间的Grid,也即是当前JavaScript的错误列表。 
树与递归 
只要有树的地方就少不了递归函数,因此这段代码对于我们理解递归也很有帮助。 
首先看看页面初始化代码:
01.protected void Page_Load(object sender, EventArgs e) 02.{ 03.    if (!IsPostBack) 04.    { 05.        LoadData(true); 06.    } 07.} 08.#region LoadData 09.private void LoadData(bool showAllErrors) 10.{ 11.    btnExpandAll.OnClientClick = Tree1.GetExpandAllNodesReference(); 12.    btnCollapseAll.OnClientClick = Tree1.GetCollapseAllNodesReference(); 13.    string treestr = GetFileContent("~/data/json/tree.json"); 14.    List<string> treePathList = new List<string>(); 15.    ResolveMenuTree(new JSONArray(treestr), treePathList, showAllErrors, Tree1.Nodes); 16.} 17.private string GetFileContent(string path) 18.{ 19.    string treestr = String.Empty; 20.    using (StreamReader sr = new StreamReader(Server.MapPath(path))) 21.    { 22.        treestr = sr.ReadToEnd(); 23.    } 24.    return treestr; 25.} 26.private void ResolveMenuTree(JSONArray ja, List<string> treePathList, bool showAllErrors, ExtAspNet.TreeNodeCollection nodes) 27.{ 28.    // TODO 递归生成树 29.} 30.private string GetTreePath(List<string> treePath) 31.{ 32.    string path = String.Empty; 33.    foreach (string node in treePath) 34.    { 35.        path += node + "/"; 36.    } 37.    return path.TrimEnd('/'); 38.} 
我们通过Nii.JSON这个开源类库(已经包含在ExtAspNet中),来将JSON字符串转换为JSONArray对象,以便在递归中使用:
1.JSONArray ja = new JSONArray(treestr); 
递归生成树 
为了让大家看清问题的本质,我首先放出一个简单的递归,只完成基本功能:
01.private void ResolveMenuTree2(JSONArray ja, List<string> treePathList, bool showAllErrors, ExtAspNet.TreeNodeCollection nodes) 02.{ 03.    for (int i = 0; i < ja.Count; i++) 04.    { 05.        JSONObject kid = ja[i] as JSONObject; 06.        string name = kid.getString("name"); 07.        // 当前路径,如果basePath存在说明是根目录 08.        if (kid.has("basePath")) 09.        { 10.            treePathList.Add(kid.getString("basePath")); 11.        } 12.        else13.        { 14.            treePathList.Add(name); 15.        } 16.        string currentPath = GetTreePath(treePathList); 17.        string type = kid.getString("type"); 18.        // 如果文件夹中没有文件,则不添加此文件夹 19.        if (type == "folder" && kid.getInt("fileCount") == 0) 20.        { 21.            treePathList.RemoveAt(treePathList.Count - 1); 22.            continue; 23.        } 24.        ExtAspNet.TreeNode node = new ExtAspNet.TreeNode(); 25.        nodes.Add(node); 26.        node.Text = name; 27.        node.Text = String.Format("<span qtip=\"{0}\">{1}</span>", currentPath, node.Text); 28.        if (type == "folder") 29.        { 30.            node.SingleClickExpand = true; 31.            ResolveMenuTree2(kid.getJSONArray("kids"), treePathList, showAllErrors, node.Nodes); 32.        } 33.        else34.        { 35.            node.Leaf = true; 36.        } 37.        treePathList.RemoveAt(treePathList.Count - 1); 38.    } 39.} 
在这段代码中,我们通过treePathList来记录当前节点的路径,这也是一个关键点。 
此时生成的页面截图: 
 
完整的代码(根据错误设置节点颜色,同时为有错误的节点可回发):
001.private void ResolveMenuTree(JSONArray ja, List<string> treePathList, bool showAllErrors, ExtAspNet.TreeNodeCollection nodes) 002.{ 003.    for (int i = 0; i < ja.Count; i++) 004.    { 005.        JSONObject kid = ja[i] as JSONObject; 006.        string name = kid.getString("name"); 007.        // 当前路径,如果basePath存在说明是根目录 008.        if (kid.has("basePath")) 009.        { 010.            treePathList.Add(kid.getString("basePath")); 011.        } 012.        else013.        { 014.            treePathList.Add(name); 015.        } 016.        string currentPath = GetTreePath(treePathList); 017.        // 获取JSLint错误数 018.        JSONArray errors = kid.getJSONArray("errors"); 019.        int errorCount = errors.getInt(0); 020.        int criticalErrorCount = errors.getInt(1); 021.        if (showAllErrors) 022.        { 023.            if (errorCount > 0) 024.            { 025.                name += String.Format(" ({0})", errorCount); 026.            } 027.        } 028.        else029.        { 030.            if (criticalErrorCount > 0) 031.            { 032.                name += String.Format(" ({0})", criticalErrorCount); 033.            } 034.        } 035.        string type = kid.getString("type"); 036.        // 如果文件夹中没有文件,则不添加此文件夹 037.        if (type == "folder" && kid.getInt("fileCount") == 0) 038.        { 039.            treePathList.RemoveAt(treePathList.Count - 1); 040.            continue; 041.        } 042.        ExtAspNet.TreeNode node = new ExtAspNet.TreeNode(); 043.        nodes.Add(node); 044.        node.Text = name; 045.        //node.ToolTip = currentPath; 046.        // 节点的显示颜色 047.        string style = ""; 048.        if (showAllErrors) 049.        { 050.            if (errorCount == 0) 051.            { 052.                style = "color:green;"; 053.            } 054.            else055.            { 056.                if (criticalErrorCount == 0) 057.                { 058.                    style = "color:#FF9900;"; 059.                } 060.                else061.                { 062.                    style = "color:#FF0000;"; 063.                } 064.            } 065.        } 066.        else067.        { 068.            if (criticalErrorCount != 0) 069.            { 070.                style = "color:#FF0000;"; 071.            } 072.            else073.            { 074.                style = "color:green;"; 075.            } 076.        } 077.        node.Text = String.Format("<span qtip=\"{2}\" style=\"{0}\">{1}</span>", style, node.Text, currentPath); 078.        if (type == "folder") 079.        { 080.            node.SingleClickExpand = true; 081.            ResolveMenuTree(kid.getJSONArray("kids"), treePathList, showAllErrors, node.Nodes); 082.        } 083.        else084.        { 085.            node.Leaf = true; 086.            if (showAllErrors) 087.            { 088.                if (errorCount != 0) 089.                { 090.                    node.EnablePostBack = true; 091.                    node.CommandName = currentPath; 092.                } 093.            } 094.            else095.            { 096.                if (criticalErrorCount != 0) 097.                { 098.                    node.EnablePostBack = true; 099.                    node.CommandName = currentPath; 100.                } 101.            } 102.        } 103.        treePathList.RemoveAt(treePathList.Count - 1); 104.    } 105.} 
下一章将讲述如何点击左侧树节点时更新中间的Grid控件,并加载右侧的IFrame(即JavaScript文件的内容)。 
本站文章除注明转载外,均为本站原创或翻译。欢迎任何形式的转载,但请务必注明出处、不得修改原文相关链接,如果存在内容上的异议请邮件反馈至chenjj@ldacury.cn
文章转载自:博客园