1. 程式人生 > >帶有『選擇次數排序』和『搜尋』功能的樹形控制元件設計與實現

帶有『選擇次數排序』和『搜尋』功能的樹形控制元件設計與實現

一、思想創意

樹形控制元件是軟體操作介面中最常見的一種資料展現控制元件,如下圖所示:

圖1

這就是我們常見的樹形結構,目前有很多樹控制元件可以供我們選擇使用,如zTree、Ext中的樹控制元件,等等。

樹形控制元件這麼多,但實現的功能就是上面這張圖,樹形結構圖,用來展現具有層次結構的資料項。那麼樹形控制元件能否改進一下,實現更加靈活、便捷的功能呢?讓我們先來看幾個用例場景。

這是某某管理資訊系統的操作介面,如圖所示:

圖2

介面中有一個輸入域是選擇家庭住址,採用的是下拉樹的形式。預設展開第一層節點,也就是北京市下屬的“區”名稱,操作員可以通過點選“區”名稱前面的加號,展開某個區,例如上圖中,操作員展開了 “北京市→順義區→木林鎮→榮各莊村”,家庭住址細化到村一級。利用下拉樹的形式,讓操作員選擇,可以避免操作員手工輸入時發生的錯誤。但是這樣做也有缺點,操作員選擇起來很麻煩,北京市順義區下面的村鎮有很多,操作員要找到某個村,很費勁,得展開很多級節點,而且還要在數百個村鎮中找到要選擇的那一個。

能不能在下拉樹的基礎上,改進一下,使得操作員選擇起來更加快捷、方便呢?看下面這個圖,這是改進之後的介面:

圖3

在下拉樹上面增加幾個功能,一個叫“排序”,一個叫“恢復預設”,還有一個叫“搜尋”,下面依次介紹這幾個功能。

1、搜尋
先說搜尋功能,這裡所謂的搜尋,就是操作員在輸入框中輸入一個關鍵字,然後點選“搜尋”按鈕,下面展示出包含關鍵字的樹形結構,例如操作員在輸入框中輸入“村”字,點選搜尋按鈕,介面顯示如下:

圖4

下拉樹中顯示出帶有“村”字的地名,包括二郎廟村、一街村、榮各莊村。如果操作員想選擇“榮各莊村”的話,很容易就找到了。這個功能就是通過搜尋樹節點的關鍵字來縮小查詢範圍,使得操作員更快捷的找到所需選項。

這個功能有點類似於列表查詢功能,如圖所示:

圖5

在查詢條件輸入框中輸入查詢關鍵字,點選查詢按鈕,列表中顯示出滿足條件的查詢結果,供使用者選擇。

但是對樹形結構的搜尋是比較複雜的,需要從整棵樹的根節點開始,逐個節點過濾,把包含關鍵字的節點全部找到,然後給使用者展示出來。要實現這個功能,首先需要對整棵樹進行全載入,而不是延遲載入,然後在客戶端利用JavaScript程式設計實現節點搜尋功能,最後把搜尋出的節點展示出來。

搜尋功能先介紹到這兒,後面會詳細介紹實現方法。

2、排序
有了搜尋功能,操作員就很容易通過關鍵字找到他所需的選項,但是有些操作員覺得輸入文字比較麻煩,能不能不用輸入文字,也能更快的找到所需選項呢?這就是排序功能。

這個功能是一種智慧化的功能,這個排序不是簡單的列表排序,一般的列表排序如下圖所示:

圖6

上圖中的資料列表,表頭列上有『上下箭頭(∧∨)』圖示,使用者點選排序箭頭後,系統按該列進行排序,每一列表頭上都有排序圖示,使用者可以按照任何一列進行排序。

樹形結構預設也有順序,一般是按照節點編號或節點名稱排序,每一層節點都按照節點編號或節點名稱排序,類似於Oracle中的層次查詢排序,也就是兄弟節點排序,這是通常的排序方式。

那麼,我們這裡所說的“排序”指的是什麼意思呢?這裡所說的排序方式不是按照節點編號或者節點名稱進行兄弟節點排序,而是按照節點的“選擇次數”排序。

“選擇次數”指的就是某一節點被操作員選擇的次數(也就是被操作員點選的次數)。例如,“北京市→順義區→木林鎮→榮各莊村”,榮各莊村被操作員選擇過8次,榮各莊村的選擇次數就是8; 而“北京市→順義區→楊鎮→李各莊村”,李各莊村被操作員選擇過3次,李各莊村的選擇次數就是3。按“選擇次數”排序,可以使選擇次數高的節點排在樹形結構的前面,使操作員可以優先找到選擇次數高的節點,這些節點很可能就是操作員這一次選擇時仍然要選擇的節點(至少選擇的概率比較大)。例如,榮各莊村被選擇過8次,李各莊村被選擇過3次,那麼,操作員這一次還有可能選擇榮各莊村,這是一種合理的推論,就是說操作員以前頻繁選擇哪個節點,那麼下一次還可能選擇那個節點。把選擇次數高的節點排在樹形結構的前面,有利於操作員尋找他頻繁選擇過的節點。

看下面兩張圖,

圖7

圖8

圖7是操作員點選『排序』之前的下拉樹介面,圖8是操作員點選『排序』之後的下拉樹介面,假如榮各莊村被操作員選擇過8次,其它村莊的選擇次數都比榮各莊村少,操作員點選『排序』之後,系統經過計算,將“北京市→順義區→木林鎮→榮各莊村”排在了樹形結構的前面,順義區排在了海淀區前面,木林鎮也排在了楊鎮前面,而排序之前,順義區是排在海淀區後面的,木林鎮是排在楊鎮之後的。樹形結構的排序比普通的列表排序要複雜,它複雜在:移動子節點的同時,也要移動它的父節點,這樣才能保持樹形結構的完整性,也就是說無論怎麼排序,它都是一棵完整的樹形結構,並且父子關係不能發生變化,“北京市→順義區→木林鎮→榮各莊村”整條路徑都要向上移動。

這就是樹形結構的排序,不是按照節點編號或節點名稱排序,而是按照節點的選擇次數排序。排序之後不能破壞原有的父子關係,要保持樹的完整性。這個『排序』也可以叫做『按選擇次數排序』。

排序功能先介紹到這兒,後面會詳細介紹實現方法。

3、恢復預設
當操作員點選『排序』按鈕後,下拉樹按照節點選擇次數排序,如果要恢復成預設排序方式,也就是按節點編號排序或節點名稱排序,那麼,點選一下『恢復預設』按鈕,就可以恢復成原來的預設排序方式。

當操作員點選『搜尋』按鈕後,下拉樹顯示出篩選後的樹形結構資料,如果要恢復成全部樹形結構資料,那麼,點選一下『恢復預設』按鈕,就可以恢復成原來的資料了。

這就是『恢復預設』功能,後面會詳細介紹實現方法。

二、概要設計

要實現 『搜尋』和 『按選擇次數排序』,需要將JavaScript樹形控制元件和後臺Java程式結合起來,同時還需要使用一種資料格式:JSON巢狀格式(也叫做樹形結構JSON),這種資料格式在Ext的樹形控制元件 和 zTree中都有使用。

如圖:

圖9

這裡所用的JavaScript樹形控制元件需要支援JSON巢狀格式,便於客戶端程式設計處理,因為JSON格式很容易轉換成JavaScript物件,我猜測JavaScript樹形控制元件也是利用JSON的這個優勢,通過先序遍歷JavaScript樹狀物件,在Html頁面上打印出樹形檢視。『搜尋』 和 『按選擇次數排序』都是建立在這個JavaScript樹狀物件之上的。

這個樹狀的JavaScript物件是由JSON巢狀格式轉換而來的,其實一個 eval() 方法就可以把JSON格式的資料轉換成JavaScript樹狀物件。

JavaScript樹形控制元件的工作原理,如下:

圖10

『搜尋』 和 『按選擇次數排序』都需要在JavaScript樹形控制元件上做文章。如圖所示:

圖11

我做了一個帶有『搜尋』 和 『按選擇次數排序』功能的樹形選單Demo演示程式,先看一下圖例:

圖12

這是一個展示北京郊區村鎮的樹形結構檢視,一共四級節點:市、區、鎮、村。在這個樹形檢視上面增加了兩個功能:『按選擇次數排序』和『搜尋』,還有一個按鈕叫『恢復預設』。

下面對該Demo做一下演示:

1、搜尋
先在輸入框中輸入“榮各莊”三個字,點選『搜尋』按鈕,

圖13

圖14

“榮各莊村”被搜尋出來了,其它的選單節點都被隱藏了,只篩選出被搜尋的節點。使用者很容易就找到“榮各莊村”這個節點了,很方便吧。

再試一次,輸入“楊鎮”二字,點選『搜尋』按鈕,

圖15

楊鎮和它下面的三個村子都被搜尋出來,也就是說,如果搜尋的節點下面有孩子節點,那麼該節點和它的孩子節點都被搜尋出來,方便使用者選擇。

2、按選擇次數排序
這個功能可以把選擇次數高的節點排在前面,選擇次數少的節點排在後面,方便使用者選擇以前曾經選過的頻度高的節點。

先點選三次“榮各莊村”這個節點,

圖16

再點選一次“二郎廟村”這個節點,

圖17

點選『按選擇次數排序』按鈕,結果如下:

圖18

“榮各莊村”和“二郎廟村”都排在了前面,它們的父節點也都排在了前面,也就是說,節點的排序是整條路徑排序,例如“北京市→順義區→木林鎮→榮各莊村”就是一條完整路徑,這條路徑整體都移動到了最前面,楊鎮排在了第二位,“二郎廟村”在楊鎮下面的三個村中排在了第一位,原來它是第三位。

『按選擇次數排序』和普通的『按節點編號排序』或『按節點名稱排序』是不一樣的,它的排序規則是有邏輯性的。『按選擇次數排序』也可以叫做“路徑權值”排序,它採用“兄弟節點橫向排序”方法來實現,後面會詳細介紹這些概念。

3、 恢復預設
這個功能很簡單,就是恢復成樹形選單的初始狀態。

圖19

通過『按選擇次數排序』和『搜尋』這兩個功能,使用者可以方便的對樹形檢視進行篩選和排序,『按選擇次數排序』是一種智慧化的功能,系統自動計算出選擇次數高的節點,將它們由高到低排列,它建立在一種合理的推論之上:使用者以前頻繁選擇的節點,這次可能還要選擇它們,至少選擇它們的概率比較大。『搜尋』功能也是很實用的,在實際的應用系統中,樹形控制元件的資料量很大,有的多達數百個節點或上千個節點,使用者可能只記得某個節點大概的名字,具體名字記不住,要想找到它們,只要在搜尋框中輸入關鍵字,就可以篩選出包含該關鍵字的節點了,縮小了選擇範圍,更加方便使用者。

三、詳細設計

那麼如何具體實現這些功能呢,下面介紹具體的實現原理。
在概要設計中,已經畫了很多圖了,尤其是圖10和圖11,畫出了樹形控制元件的工作原理,但還不夠詳細,現在我詳細介紹『按選擇次數排序』和『搜尋』這兩個功能的實現方法。下面是zTree的樹形控制元件Demo演示程式,是我從http://www.ztree.me/v3/demo.php#_101 這個網站上下載的,那是zTree V3.5版本的介紹網站,網站截圖如下:

圖20

如上圖中,點選介面右上角的『下載zTree v3.5.12』連結,把Demo演示程式下載下來。

在Demo中有一個檔案,完整路徑名稱是:
JQuery zTree v3.5.12\demo\cn\core\standardData.html,它演示的是如何展現出樹形結構。

這個檔案的原始碼如下:
standardData.html

Html程式碼  收藏程式碼
  1. <!DOCTYPE html>  
  2. <HTML>  
  3. <HEAD>  
  4.     <TITLE> ZTREE DEMO - Standard Data </TITLE>  
  5.     <meta http-equiv="content-type" content="text/html; charset=UTF-8">  
  6.     <link rel="stylesheet" href="../../../css/demo.css" type="text/css">  
  7.     <link rel="stylesheet" href="../../../css/zTreeStyle/zTreeStyle.css" type="text/css">  
  8.     <script type="text/javascript" src="../../../js/jquery-1.4.4.min.js"></script>  
  9.     <script type="text/javascript" src="../../../js/jquery.ztree.core-3.5.js"></script>  
  10.     <SCRIPT type="text/javascript">  
  11.         <!--  
  12.         var setting = { };  
  13.         var zNodes =[  
  14.             { name:"父節點1 - 展開", open:true,  
  15.                 children: [  
  16.                     { name:"父節點11 - 摺疊",  
  17.                         children: [  
  18.                             { name:"葉子節點111"},  
  19.                             { name:"葉子節點112"},  
  20.                             { name:"葉子節點113"},  
  21.                             { name:"葉子節點114"}  
  22.                         ]},  
  23.                     { name:"父節點12 - 摺疊",  
  24.                         children: [  
  25.                             { name:"葉子節點121"},  
  26.                             { name:"葉子節點122"},  
  27.                             { name:"葉子節點123"},  
  28.                             { name:"葉子節點124"}  
  29.                         ]},  
  30.                     { name:"父節點13 - 沒有子節點", isParent:true}  
  31.                 ]},  
  32.             { name:"父節點2 - 摺疊",  
  33.                 children: [  
  34.                     { name:"父節點21 - 展開", open:true,  
  35.                         children: [  
  36.                             { name:"葉子節點211"},  
  37.                             { name:"葉子節點212"},  
  38.                             { name:"葉子節點213"},  
  39.                             { name:"葉子節點214"}  
  40.                         ]},  
  41.                     { name:"父節點22 - 摺疊",  
  42.                         children: [  
  43.                             { name:"葉子節點221"},  
  44.                             { name:"葉子節點222"},  
  45.                             { name:"葉子節點223"},  
  46.                             { name:"葉子節點224"}  
  47.                         ]},  
  48.                     { name:"父節點23 - 摺疊",  
  49.                         children: [  
  50.                             { name:"葉子節點231"},  
  51.                             { name:"葉子節點232"},  
  52.                             { name:"葉子節點233"},  
  53.                             { name:"葉子節點234"}  
  54.                         ]}  
  55.                 ]},  
  56.             { name:"父節點3 - 沒有子節點", isParent:true}  
  57.         ];  
  58.         $(document).ready(function(){  
  59.             $.fn.zTree.init($("#treeDemo"), setting, zNodes);  
  60.         });  
  61.         //-->  
  62.     </SCRIPT>  
  63. </HEAD>  
  64. <BODY>  
  65. <h1>最簡單的樹 -- 標準 JSON 資料</h1>  
  66. <h6>[ 檔案路徑: core/standardData.html ]</h6>  
  67. <div class="content_wrap">  
  68.     <div class="zTreeDemoBackground left">  
  69.         <ul id="treeDemo" class="ztree"></ul>  
  70.     </div>  
  71.     <div class="right">  
  72.         <ul class="info">  
  73.         </ul>  
  74.     </div>  
  75. </div>  
  76. </BODY>  
  77. </HTML>  

這就是實現一棵樹最簡單的方法。

要想實現我上面所提出的功能,需要增加很多程式碼,但這些程式碼與zTree無關,不會對zTree造成任何影響,而是在JSON巢狀格式資料上做文章。

修改後的完整程式碼如下:(這些程式碼可以直接拷貝下來執行測試,檔名稱還叫“standardData.html”,
可以把該檔案覆蓋zTree V3.5 Demo演示程式中的同名檔案:
JQuery zTree v3.5.12\demo\cn\core\standardData.html,覆蓋之後,用IE瀏覽器開啟執行,檢視演示效果。)

standardData.html

Html程式碼  收藏程式碼
  1. <!DOCTYPE html>  
  2. <HTML>  
  3. <HEAD>  
  4.     <TITLE> ZTREE DEMO - Standard Data </TITLE>  
  5.     <meta http-equiv="content-type" content="text/html; charset=UTF-8">  
  6.     <link rel="stylesheet" href="../../../css/demo.css" type="text/css">  
  7.     <link rel="stylesheet" href="../../../css/zTreeStyle/zTreeStyle.css" type="text/css">  
  8.     <script type="text/javascript" src="../../../js/jquery-1.4.4.min.js"></script>  
  9.     <script type="text/javascript" src="../../../js/jquery.ztree.core-3.5.js"></script>  
  10.     <SCRIPT type="text/javascript">  
  11.         <!--  
  12.         // 樹形結構的資料在這裡是寫死的,實際應用中,是從資料庫中讀出的,存在request物件中,  
  13.         // 然後用request.getAttribute()方法,從一個變數中讀出來,  
  14.         // 實際應用中應該是:var zNodes = <%=request.getAttribute("data")%> ,是從request中動態讀出來的,  
  15.         // 關於如何拼接生成這種JSON巢狀格式的字串,可以參考《附錄一:多叉樹結合JavaScript樹形控制元件實現  
  16.         // 無限級樹形結構(一種構建多級有序樹形結構JSON(或XML)資料來源的方法)》,  
  17.         // 《附錄一》是專門介紹如何生成JSON巢狀格式的資料,  
  18.         // 注:下面的這個zNodes資料格式,我是在原有zTree標準資料格式的基礎上擴充套件了一些屬性,凡是以ex_開頭  
  19.         // 的屬性都是我擴充套件增加的,標準資料格式中沒有,這些額外增加的屬性,zTree是  
  20.         // 不會解析的,是我用來實現『按節點選擇次數排序』和『搜尋』功能時用到的,後臺Java程式在構造資料時,  
  21.         // 需要構造成下面這個樣子。  
  22.         //   
  23.         // (注:擴充套件屬性的含義:  
  24.         // ex_uid:節點編號  
  25.         // ex_pid:父節點編號  
  26.         // ex_weight:節點選擇次數(權值)  
  27.         // ex_visible:節點可見性  
  28.         // ex_parentNode:父節點引用)  
  29.         var zNodes = [  
  30.       {  
  31.         name: '北京市',  
  32.         ex_uid: '0',  
  33.         ex_pid: '',  
  34.         ex_weight: 0,  
  35.         ex_visible: true,  
  36.         ex_parentNode: null,  
  37.         children: [  
  38.           {  
  39.             name: '順義區',  
  40.             ex_uid: '2',  
  41.             ex_pid: '0',  
  42.             ex_weight: 0,  
  43.             ex_visible: true,  
  44.             ex_parentNode: null,  
  45.             children: [  
  46.               {  
  47.                 name: '楊鎮',  
  48.                 ex_uid: '3',  
  49.                 ex_pid: '2',  
  50.                 ex_weight: 0,  
  51.                 ex_visible: true,  
  52.                 ex_parentNode: null,  
  53.                 children: [  
  54.                   {  
  55.                     name: '李各莊村',  
  56.                     ex_uid: '4',  
  57.                     ex_pid: '3',  
  58.                     ex_weight: 0,  
  59.                     ex_visible: true,  
  60.                     ex_parentNode: null  
  61.                   },  
  62.                   {  
  63.                     name: '一街村',  
  64.                     ex_uid: '5',  
  65.                     ex_pid: '3',  
  66.                     ex_weight: 0,  
  67.                     ex_visible: true,  
  68.                     ex_parentNode: null  
  69.                   },  
  70.                   {  
  71.                     name: '二郎廟村',  
  72.                     ex_uid: '6',  
  73.                     ex_pid: '3',  
  74.                     ex_weight: 0,  
  75.                     ex_visible: true,  
  76.                     ex_parentNode: null  
  77.                   }  
  78.                 ]  
  79.               },  
  80.               {  
  81.                 name: '木林鎮',  
  82.                 ex_uid: '7',  
  83.                 ex_pid: '2',  
  84.                 ex_weight: 0,  
  85.                 ex_visible: true,  
  86.                 ex_parentNode: null,  
  87.                 children: [  
  88.                   {  
  89.                     name: '榮各莊村',  
  90.                     ex_uid: '8',  
  91.                     ex_pid: '7',  
  92.                     ex_weight: 0,  
  93.                     ex_visible: true,  
  94.                     ex_parentNode: null  
  95.                   }  
  96.                 ]  
  97.               },  
  98.               {  
  99.                 name: '龍灣屯鎮',  
  100.                 ex_uid: '9',  
  101.                 ex_pid: '2',  
  102.                 ex_weight: 0,  
  103.                 ex_visible: true,  
  104.                 ex_parentNode: null,  
  105.                 children: [  
  106.                   {  
  107.                     name: '王泮莊村',  
  108.                     ex_uid: '15',  
  109.                     ex_pid: '9',  
  110.                     ex_weight: 0,  
  111.                     ex_visible: true,  
  112.                     ex_parentNode: null  
  113.                   }  
  114.                 ]  
  115.               },  
  116.               {  
  117.                 name: '李遂鎮',  
  118.                 ex_uid: '10',  
  119.                 ex_pid: '2',  
  120.                 ex_weight: 0,  
  121.                 ex_visible: true,  
  122.                 ex_parentNode: null,  
  123.                 children: [  
  124.                   {  
  125.                     name: '柳各莊村',  
  126.                     ex_uid: '14',  
  127.                     ex_pid: '10',  
  128.                     ex_weight: 0,  
  129.                     ex_visible: true,  
  130.                     ex_parentNode: null  
  131.                   }  
  132.                 ]  
  133.               }  
  134.             ]  
  135.           },  
  136.           {  
  137.             name: '平谷區',  
  138.             ex_uid: '11',  
  139.             ex_pid: '0',  
  140.             ex_weight: 0,  
  141.             ex_visible: true,  
  142.             ex_parentNode: null,  
  143.             children: [  
  144.               {  
  145.                 name: '夏各莊鎮',  
  146.                 ex_uid: '12',  
  147.                 ex_pid: '11',  
  148.                 ex_weight: 0,  
  149.                 ex_visible: true,  
  150.                 ex_parentNode: null,  
  151.                 children: [  
  152.                   {  
  153.                     name: '馬各莊村',  
  154.                     ex_uid: '13',  
  155.                     ex_pid: '12',  
  156.                     ex_weight: 0,  
  157.                     ex_visible: true,  
  158.                     ex_parentNode: null  
  159.                   }  
  160.                 ]  
  161.               }  
  162.             ]  
  163.           }  
  164.         ]  
  165.       }  
  166.         ];        
  167.         var setting = {  
  168.             callback: {  
  169.                 onClick: clickNode  
  170.             }     
  171.         };  
  172.         // 單擊節點後觸發的事件,  
  173.         // 在這個方法裡,做兩件事:  
  174.         //  
  175.         // 1、增加節點所在路徑的權值(也叫做『路徑向上加權』),這裡的『路徑向上加權』使用的方法與  
  176.         // 《附錄二:新概念『智慧樹形選單』--利用加權多叉樹結合JavaScript樹形控制元件實現》中的路徑加權方法不一樣,這是由於在JavaScript中無法建立  
  177.         // 像Java中的那種帶有雙向引用的多叉樹結構(即父節點引用子節點,子節點引用父節點),在JavaScript中如果做這種雙向引用的話,會造成  
  178.         // 『Stack overflow』異常,所以只能分別建立兩棵多叉樹物件,一棵是原始樹形結構物件,另一棵是利用nodeMap建立的多叉樹物件,專門用於  
  179.         // 反向引用,即子節點對父節點的引用。而在Java中,直接可以根據一個節點的父節點引用,找到它所有的父節點。但是在這裡,只能採用一種笨  
  180.         // 辦法,先從反向引用的多叉樹中找到某一節點的所有父節點,存在一個數組裡,然後在原始樹形結構物件中使用先序遍歷方法,從頂向下依次查詢,  
  181.         // 把某一節點的所有父節點的權值加1,效率較低,但與利用反向引用查詢父節點的方法目的是一樣的。  
  182.         //  
  183.         // 2、更新節點選擇次數到資料庫中,以備下次登入系統時恢復原資料  
  184.         function clickNode(event, treeId, treeNode, clickFlag) {  
  185.             var parentNodes = [];  
  186.             var currentNode = nodeMap['_' + treeNode.ex_uid];  
  187.             var parentNode = currentNode.ex_parentNode;   
  188.             while (parentNode != null) {  
  189.                 parentNodes.push(parentNode);             
  190.                 parentNodeparentNode = parentNode.ex_parentNode;                        
  191.             }             
  192.             parentNodes.push(currentNode);  
  193.             increaseNodesWeight(zNodes[0], parentNodes);  
  194.             // 更新節點選擇次數到資料庫中,以備下次登入系統時恢復原資料  
  195.             modifyNodeWeigthToDB();  
  196.         }  
  197.         // 更新節點選擇次數到資料庫中,  
  198.         // 由於沒有資料庫,所以暫時不實現這個方法,實際應用時需要實現該方法  
  199.         function modifyNodeWeigthToDB() {  
  200.             // todo  
  201.         }  
  202.         // 增加節點所在路徑的權值  
  203.         function increaseNodesWeight(node, parentNodes) {  
  204.             if (containNode(node, parentNodes)) {  
  205.                 node.ex_weight++;  
  206.             }  
  207.             if (node.children && node.children.length != 0) {  
  208.                 var i = 0;  
  209.                 for (; i < node.children.length; i++) {  
  210.                         if (containNode(node, parentNodes)) {  
  211.                             increaseNodesWeight((node.children)[i], parentNodes);  
  212.                         }  
  213.                 }  
  214.                 // 如果在本層節點中沒有找到要增加權值的節點,說明需要增加權值的節點都已經找完了,  
  215.                 // 不需要再向下一層節點中尋找了,直接退出遞迴函式  
  216.                 if (i == node.children.length - 1) {  
  217.                     return;  
  218.                 }  
  219.             }  
  220.         }  
  221.         // 排序方法:按照節點選擇次數排序【冒泡法排序】  
  222.         // 節點選擇次數大的排在前面,如果次數相等,按照編號排,編號小的排在前面  
  223.         function bubbleSortByWeight(theArray) {  
  224.                 var temp;  
  225.           for (var i = 0; i < theArray.length-1; i++) {        
  226.               for (var j = theArray.length - 1; j > i ; j--) {         
  227.                   if (theArray[j].ex_weight > theArray[j - 1].ex_weight) {  
  228.                     temp = theArray[j];   
  229.                     theArray[j] = theArray[j - 1];  
  230.                     theArray[j - 1] = temp;  
  231.                   } else if (theArray[j].ex_weight == theArray[j - 1].ex_weight) {  
  232.                             if (theArray[j].ex_uid < theArray[j - 1].ex_uid) {  
  233.                                 temp = theArray[j];   
  234.                         theArray[j] = theArray[j - 1];  
  235.                         theArray[j - 1] = temp;  
  236.                             }  
  237.                         }  
  238.               }  
  239.           }  
  240.         }  
  241.         // 排序方法:按照節點編號排序,編號小的排在前面【冒泡法排序】  
  242.         function bubbleSortByUid(theArray) {  
  243.                 var temp;  
  244.           for (var i = 0; i < theArray.length-1; i++) {        
  245.               for (var j = theArray.length - 1; j > i ; j--) {         
  246.                   if (theArray[j].ex_uid < theArray[j - 1].ex_uid) {  
  247.                     temp = theArray[j];   
  248.                     theArray[j] = theArray[j - 1];  
  249.                     theArray[j - 1] = temp;  
  250.                   }  
  251.               }  
  252.           }  
  253.         }  
  254.         // 按照節點選擇次數對樹形結構進行兄弟節點排序【遞迴排序】  
  255.         function orderSiblingsByWeight(node) {  
  256.             if (node.children && node.children.length != 0) {  
  257.                 bubbleSortByWeight(node.children);  
  258.                 for (var i = 0; i < node.children.length; i++) {  
  259.                     orderSiblingsByWeight((node.children)[i]);  
  260.                 }  
  261.             }  
  262.         }  
  263.         // 按照節點編號對樹形結構進行兄弟節點排序【遞迴排序】  
  264.         function orderSiblingsByUid(node) {  
  265.             if (node.children && node.children.length != 0) {  
  266.                 bubbleSortByUid(node.children);  
  267.                 for (var i = 0; i < node.children.length; i++) {  
  268.                     orderSiblingsByUid((node.children)[i]);  
  269.                 }  
  270.             }  
  271.         }  
  272.         // 設定樹節點為“不可見”狀態【先序遍歷法】  
  273.         function setTreeNotVisible(root) {  
  274.             root.ex_visible = false;  
  275.             if (root.children && root.children.length != 0) {  
  276.                 for (var i = 0; i < root.children.length; i++) {  
  277.                         setTreeNotVisible((root.children)[i]);  
  278.                 }  
  279.             }  
  280.         }  
  281.         // 設定樹節點為“可見”狀態【先序遍歷法】  
  282.         function setTreeVisible(root) {  
  283.             root.ex_visible = true;  
  284. 相關推薦

    帶有選擇次數排序搜尋功能樹形控制元件設計實現

    一、思想創意 樹形控制元件是軟體操作介面中最常見的一種資料展現控制元件,如下圖所示: 圖1 這就是我們常見的樹形結構,目前有很多樹控制元件可以供我們選擇使用,如zTree、Ext中的樹控制元件,等等。 樹形控制元件這麼多,但實現的功能就是上面這張圖,樹

    [原始碼和文件分享]基於VS2012SQL SERVER的餐廳點餐系統設計實現

    一、需求分析 1. 面向物件 點典點菜系統是一款面向顧客和管理人員的全方面系統,其中管理人員又包括服務員、採購員和廚師。本組認真分析了不同物件的需求,為不同的物件都設計了獨特的系統功能。簡化了傳統點菜、燒菜和採購方式繁瑣的步驟,為顧客提供便捷操作的同時提高酒店管理的效率。 2. 市場背景

    遞迴組裝Cascader 級聯選擇Tree 樹形控制元件結構的資料

    以商品分類表為例,重點看分類ID和父分類ID public List<Map<String,Object>> getGoodsCategoryTree() { //1.獲取所有商品分類,條件:category_id!=0(0為頂級選單的父類I

    《Linux內核設計實現》讀書筆記(十六)- 頁高速緩存頁回寫

    第一次 源碼 進行 lose 減少 文件緩存 掩碼 recycle 創建 主要內容: 緩存簡介 頁高速緩存 頁回寫 1. 緩存簡介 在編程中,緩存是很常見也很有效的一種提高程序性能的機制。 linux內核也不例外,為了提高I/O性能,也引入了緩存機

    Redis 設計實現 (八)--排序、慢查詢日誌、監視器

    監視 strong add 2.4 bsp log 格式 sadd 請求 一、排序 SORT <key> 對一個數字值的key進行排序 1、alpha 對字符串類型的鍵進行排序 2、asc / desc   redis 默認升序排序asc

    基於ARMLinux的嵌入式Web Server設計實現_愛學術——免費下載

    重要 image 平臺 服務 linu amp 設計與實現 體系 www. 【摘要】介紹了嵌入式ARM處理器的特點和硬件平臺的設計、嵌入式操作系統的設計,構建了基於嵌入式Web Server的遠程監測系統結構,重點分析了嵌入式TCP/IP協議棧的體系結構、嵌入式Web服務器

    純前端表格控制元件SpreadJSJava結合,實現模板上傳下載等功能

    安裝部署: 開發環境: 後臺伺服器端採用 Java 、SpringMVC。 資料儲存到 \demo_web\WEB-INF\FileDatabase.txt 檔案中,不需要依賴DB。 採用 Eclipse Java EE IDE for Web Develope

    android 閃屏頁的倒計時傳送驗證碼的倒計時控制元件

    TimeCount。直接上程式碼。 import android.os.CountDownTimer; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.

    winformwpf下分別使用zedgraph控制元件

    一、基本概念 ZedGraph是用於建立任意資料的二維線型、條型、餅型圖表的一個類庫,也可以作為Windows窗體使用者控制元件和Asp.Net網頁控制元件。這個類庫具有高度的適應性,幾乎所有式樣的圖表都能夠被建立。這個類庫的用法在於通過提供所有圖表屬性的省缺值來保持使用性的簡單。這個類庫包含了

    一個RtspServer的設計實現RTSP2.0簡介

      前段時間著手實現了一個RTSP Server,能夠正常實現多路RTSP流的直播播放,因專案需要,只做了對H.264和AAC編碼的支援,但是相信其他編碼的實現基本邏輯也是想通的。這裡我把主要設計和思考過程,以及實現框架分享一下。因為關注的是直播,這裡只討論RTSP直播協議。 RT

    [文件原始碼分享] 基於Python的PyGame的俄羅斯方塊遊戲設計實現

    近年來,隨著遊戲產業的突飛猛進,遊戲玩家的技術也是與日俱增,當你看見遊戲高手完美的表演時,你是否想過我也能達到那種水平,本程式用Python語言編寫俄羅斯方塊,左側顯示正在執行的遊戲,右邊顯示下一個出現的形狀、等級和積分等。遊戲執行時隨著等級的提高而速度加快,這需要玩家快速操作。因此,本程式主要意義是為高手玩

    Redis 設計實現之RDB AOF 兩種持久化模式詳解

    在執行情況下, Redis 以資料結構的形式將資料維持在記憶體中, 為了讓這些資料在 Redis 重啟之後仍然可用, Redis 分別提供了 RDB 和 AOF 兩種持久化模式。 在 Redis 執行時, RDB 程式將當前記憶體中的資料庫快照儲存到磁碟檔案中, 在 Red

    Android AlertDialog大小位置的設定,取得內部控制元件例項

    初始化AlertDialog AlertDialog.Builder builder=new AlertDialog.Builder(MainActivity.this); builder.setView(R.layout.dialog_item01); AlertDialog dialog=bui

    鬥地主演算法的設計實現 一 專案介紹 如何定義構造一張牌

                    大學期間,我在別人的基礎上,寫了一個簡易的鬥地主程式。主要實現了面向物件設計,洗牌、發牌、判斷牌型、比較牌的大小、遊戲規則等演算法。通過這個鬥地主小專案的練習,提高了我的面向物件設計能力,加深了對演算法的理解。最近把這些設計和演算法分享給大家,過些天會上傳鬥地主程式的原始碼。專

    [原始碼和文件分享]基於ASP.NETSQL SERVER資料庫的招聘網站設計實現

    摘 要 本課題是基於網際網路與資料庫技術的網上招聘網站,是先進的計算機科學技術和現代招聘理念相結合的產物,通過使用以ASP.NET技術為基礎,基本實現網上招聘網站的基本功能,滿足了求職者和招聘企業的需求,實現了招聘單位和求職者的雙向選擇,對於求職者檢視崗位和簡歷投遞進度有很大的幫助,本網站收集大

    [連載]《C#通訊(串列埠網路)框架的設計實現》- 0.前言

                                  目       錄 前言 前言       剛參加工作,使用過VB、VC開發軟體,隨著C#的崛起,聽說是C++++,公司決定以後開發軟體使用C#,憑藉在書市5塊錢買C#程式設計入門書籍,開始了職業生涯。開發C/S、B/S結構的軟體是

    9.Linux核心設計實現 P91---中斷中斷處理程式 (轉)

          中斷還是中斷,我講了很多次的中斷了,今天還是要講中斷,為啥呢?因為在作業系統中,中斷是必須要講的..       那麼什麼叫中斷呢, 中斷還是打斷,這樣一說你就不明白了。唉,中斷還真是有點像打斷。我們知道linux管理所有的硬體裝置,要做的第一件事先是通訊。然後,我們天天在說一句話:處理器的速度跟

    [連載]《C#通訊(串列埠網路)框架的設計實現》-2.框架的總體設計

    目       錄 C#通訊(串列埠和網路)框架的設計與實現... 1 (SuperIO)- 框架的總體設計... 1 第二章           框架總體的設計... 2 2.1           宿主程式設計... 2 2.2           通訊機制設計... 7   2.2.1   

    [連載]《C#通訊(串列埠網路)框架的設計實現》-1.通訊框架介紹

    目       錄 第一章           通訊框架介紹... 2 1.1           通訊的本質... 2 1.2           框架簡介... 3 1.3           解決現實問題... 4 1.4           應用場景... 5 1.5       

    [連載]《C#通訊(串列埠網路)框架的設計實現》- 12.二次開發及應用

    目       錄 第十二章     二次開發及應用... 2 12.1        專案配製... 3 12.2        引用相關元件... 4 12.3        構建主程式... 5 12.4        裝置驅動的開發... 6 12.4.1       假定通訊協議...