[代码] 下面是 html 调用代代码
01 | var tree = new yxTree( "tree" ); |
02 | tree.nodes[ '-1_1' ] = 'text:节点 1' ; // 这个节点添加也可以放到节点 ['1_2'] 下面添加 |
03 | tree.nodes[ '1_2' ] = 'text:节点 2' ; |
04 | tree.nodes[ '2_22' ] = 'text:节点 22' ; |
05 | tree.nodes[ '1_3' ] = 'text:节点 3' ; |
06 | tree.nodes[ '-1_14' ] = 'text:节点 14' ; |
07 | tree.nodes[ '14_13' ] = 'text:节点 13; url:http:www.baidu.com' ; |
08 | tree.nodes[ '-1_4' ] = 'text:节点 4;method:aa' ; |
09 |
10 | tree.toString( 'treeviewareaID' ); |
[代码] js 文件代码
001 | function yxTree(Tname) { |
002 | if ( typeof (Tname) != "string" || Tname == "" ){ |
003 | throw ( new Error( '创建类实例的时候请把类实例的引用变量名传递进来!' )); |
004 | } |
005 | |
006 | //【property】 |
007 | this .url = "javascript:" ; |
008 | this .target = "_self" ; |
009 | this .name = Tname; // 树实例名字 |
010 | this .wordLine = false ; |
011 | this .currentNode = null ; |
012 | this .useArrow = true ; // 是否使用方向键控制跳转到上级下级父级子级节点 |
013 | this .nodes = {}; // 使用 -1_1 格式的结点信息保存 (String) |
014 | this .node = {}; // 使用 1 格式保存的结点信息 (JSON) |
015 | this .names = "" ; // 整个树的 sourceIndex 相连的名字 |
016 | this ._d = "\x0f" ; |
017 | this .index = 0; |
018 | this .divider = "_" ; // ID 连接线 |
019 | this .rootId = "-1" ; // 根 ID |
020 | |
021 | // 样式 |
022 | this .classOpened = "Opened" ; |
023 | this .classClosed = "Closed" ; |
024 | this .classChild = "Child" ; |
025 | this .classFocus = "focusNode" ; |
026 | |
027 | //yxTree 初始化入口函数 |
028 | this .toString = function (id) { |
029 | if ($( '#yxTreeCss' ).length == 0){ // 检查是否已经添加了样式 |
030 | this .linkTreeCss(); |
031 | } |
032 | |
033 | this .dataFormat(); |
034 | |
035 | this .node[ "0" ] = { // 初始结点 |
036 | "id" : "0" , |
037 | "path" : this .rootId, |
038 | "isLoad" : false , |
039 | "hasChild" : true , |
040 | "childNodes" : [], |
041 | "childAppend" : "" , |
042 | "sourceIndex" : this .rootId, |
043 | "sourceId" : this .rootId |
044 | }; |
045 | this .nodeInit( "0" ); // 初始化生成树结点数组结构 |
046 | var str = this .generateTreeHtml( "0" ); // 生成 html |
047 | |
048 | str = '<div class="yxTree" id="yxTree_' + this .name + '">' + str + '</div>' ; |
049 |
050 | $( '#' + id).html(str); |
051 | |
052 | tree.treeInit(); // 添加样式及事件 |
053 | |
054 | return ; |
055 | }; |
056 | } |
057 |
058 | // 把所有的 nodes 结点信息,生成一个树型的数组结构 |
059 | //在数据源检索所需的数据节点 |
060 | //id 客户端节点对应的id |
061 | yxTree.prototype.nodeInit = function (id){ |
062 | var node = this .node[id], d = this .divider, _d = this ._d; |
063 | var sid = node.sourceIndex.substr(node.sourceIndex.indexOf(d) + d.length); // 取得实际的 sourceId |
064 | var reg = new RegExp( "(^|" +_d+ ")" + sid +d+ "[^" +_d+d + "]+(" +_d+ "|$)" , "g" ); |
065 | var cns = this .names.match(reg), tcn = this .node[id].childNodes; |
066 | if (cns){ |
067 | reg = new RegExp(_d, "g" ); |
068 | for ( var i=0; i<cns.length; i++) { |
069 | //初始化节点信息, 根据 this.nodes 数据源生成节点的详细信息 |
070 | //sourceIndex 数据源中的父子节点组合的字符串 0_1 |
071 | //parentId 当前树节点在客户端的父节点的 id |
072 | var sourceIndex = cns[i].replace(reg, "" ); |
073 | var parentId = id; |
074 | this .index++; |
075 | var source= this .nodes[sourceIndex]; |
076 | var text = this .getAttribute(source, "text" ); |
077 | var hint = this .getAttribute(source, "hint" ); |
078 | var url = this .getAttribute(source, "url" ); |
079 | var target = this .getAttribute(source, "target" ); |
080 | var method = this .getAttribute(source, "method" ); |
081 | var csid = sourceIndex.substr(sourceIndex.indexOf(d) + d.length); |
082 | |
083 | this .node[ this .index] = { |
084 | "id" : this .index, // id |
085 | "text" : text, // 标题 |
086 | "hint" : hint ? hint : text, // 标题提示 |
087 | "icon" : this .getAttribute(source, "icon" ), // icon |
088 | "path" : this .node[parentId].path + d + this .index, // 结点路径 |
089 | "isLoad" : false , // 是否已经加载 |
090 | "isExpand" : false , // 是否已经展开 |
091 | "parentId" : parentId, // 父结点ID |
092 | "parentNode" : this .node[parentId], // 父结点 |
093 | "sourceIndex" : sourceIndex, // 原来的索引, 如 -1_1 |
094 | "sourceId" : csid, // 原来的ID, 如上则是 id=1 |
095 | "childAppend" : "" , |
096 | "url" : url, // 结点点击url |
097 | "target" : target, // |
098 | "method" : method // 结点点击方法,只有当url 为空时才生效 |
099 | }; |
100 | this .nodes[sourceIndex] = "index:" + this .index + ";" + source; |
101 | this .node[ this .index].hasChild = this .names.indexOf( this ._d + csid + d)>-1; // 判断是否有子结点 |
102 | |
103 | tcn[tcn.length] = this .node[ this .index]; // 把初始化后的结点放入到 id 的node结点的子结点下面, 必须在下面的子结点加载方法前执行 |
104 | |
105 | if ( this .node[ this .index].hasChild) { |
106 | this .node[ this .index].childNodes = []; |
107 | this .nodeInit( this .index); // 递归读取子结点 |
108 | } |
109 | } |
110 | } |
111 | node.isLoad = true ; |
112 | }; |
113 |
114 | // 生成树的 html 代码 |
115 | yxTree.prototype.generateTreeHtml = function (id){ |
116 | var s = '<ul>' ; |
117 | var nodes = this .node[id].childNodes; |
118 | for ( var i = 0; i < nodes.length; i++){ |
119 | s += '<li id="yxTree_' + this .name + '_li_' + nodes[i].id + '" class="' + (nodes[i].hasChild?" ":" Child ") + '" nodeId= "' + nodes[i].id + '" ><span class= "s" > <span class= "icon" ></span></span>'; |
120 | if (nodes[i].url == '' && nodes[i].method != '' ){ // js 方法 |
121 | s += '<a href="javascript:' + (nodes[i].method?nodes[i].method: '' ) + '(' + this .name + '.getNode(' + nodes[i].id + '))" target="_self" title="' + nodes[i].hint + '">' ; |
122 | } else { // url |
123 | s += '<a href="' + (nodes[i].url?nodes[i].url: this .url) + '" target="' + (nodes[i].target?nodes[i].target: this .target) + '" title="' + nodes[i].hint + '">' ; |
124 | } |
125 | s += nodes[i].text + '</a>' ; |
126 | if (nodes[i].hasChild){ |
127 | s += this .generateTreeHtml(nodes[i].id); |
128 | } |
129 | s += '</li>' ; |
130 | } |
131 | s += '</ul>' ; |
132 | return s; |
133 | }; |
134 |
135 |
136 | // 根据树的html, 再添加上相应的 class (CSS) 和事件 |
137 | yxTree.prototype.treeInit = function (){ |
138 | var treeObj = this ; |
139 |
140 | $( '#yxTree_' + this .name + '.yxTree li' ).each( function (){ |
141 | var c = $( this ).attr( 'class' ); |
142 | if ( typeof (c) == 'undefined' || c == null || c == '' ){ // 把没有设置 class 内容的全部设置为关闭(closed) |
143 | $( this ).addClass(treeObj.classClosed); |
144 | } |
145 | }); |
146 | |
147 | // 增加点击事件,展开/折叠 |
148 | $( '#yxTree_' + this .name + '.yxTree span.s' ).click( function (){ |
149 | treeObj.toggleExpand($( this ).parent().attr( 'nodeId' )); |
150 | }); |
151 |
152 | $( '#yxTree_' + this .name + '.yxTree a' ).click( function (){ |
153 | treeObj.focusNodeText($( this ).parent().attr( 'nodeId' )); |
154 | }); |
155 | }; |
156 |
157 | // 聚集到某个结点 |
158 | yxTree.prototype.focusNode = function (id) { |
159 | // 把所有父结点都展开 |
160 | var node = this .node[id]; |
161 | var pNode = node.parentNode; |
162 | var path = node.path.split( this .divider); |
163 | for ( var i = 2; i < path.length; i++){ |
164 | this .expand(pNode.id); |
165 | pNode = pNode.parentNode; |
166 | } |
167 | |
168 | // 设置当前选中结点 |
169 | this .currentNode = this .node[id]; |
170 | |
171 | // 触发a点击事件 |
172 | $( '#yxTree_' + this .name + '_li_' + id).children( 'a' ).click(); |
173 | }; |
174 |
175 | // 聚集到某个结点的文本 |
176 | yxTree.prototype.focusNodeText = function (id) { |
177 | $( '#yxTree_' + this .name + '.yxTree a' ).removeClass( this .classFocus); |
178 | $( '#yxTree_' + this .name + '_li_' + id).children( 'a' ).addClass( this .classFocus); |
179 | }; |
180 |
181 | // 展开或关闭某个结点 |
182 | yxTree.prototype.toggleExpand = function (id) { |
183 | if ($( '#yxTree_' + this .name + '_li_' + id).hasClass( this .classOpened)){ |
184 | $( '#yxTree_' + this .name + '_li_' + id).removeClass( this .classOpened); |
185 | $( '#yxTree_' + this .name + '_li_' + id).addClass( this .classClosed); |
186 | } else { |
187 | $( '#yxTree_' + this .name + '_li_' + id).removeClass( this .classClosed); |
188 | $( '#yxTree_' + this .name + '_li_' + id).addClass( this .classOpened); |
189 | } |
190 | }; |
191 | yxTree.prototype.expand = function (id){ |
192 | $( '#yxTree_' + this .name + '_li_' + id).removeClass(); |
193 | $( '#yxTree_' + this .name + '_li_' + id).addClass( this .classOpened); |
194 | } |
195 | yxTree.prototype.closed = function (id){ |
196 | $( '#yxTree_' + this .name + '_li_' + id).removeClass(); |
197 | $( '#yxTree_' + this .name + '_li_' + id).addClass( this .classClosed); |
198 | } |
199 |
200 | // 展开所有结点 |
201 | yxTree.prototype.expandAll = function (){ |
202 | var classNameChild = this .classChild; |
203 | var classNameOpen = this .classOpened; |
204 | $( '#yxTree_' + this .name + '.yxTree li' ).each( function (){ |
205 | if (!$( this ).hasClass(classNameChild)){ |
206 | $( this ).removeClass(); |
207 | $( this ).addClass(classNameOpen); |
208 | } |
209 | }); |
210 | }; |
211 |
212 | // 关闭所有结点 |
213 | yxTree.prototype.closeAll = function (){ |
214 | var classNameChild = this .classChild; |
215 | var classClosed = this .classClosed; |
216 | $( '#yxTree_' + this .name + '.yxTree li' ).each( function (){ |
217 | if (!$( this ).hasClass(classNameChild)){ |
218 | $( this ).removeClass(); |
219 | $( this ).addClass(classClosed); |
220 | } |
221 | }); |
222 | }; |
223 |
224 | // 在页面中加入 css 文件 |
225 | yxTree.prototype.linkTreeCss = function (skin){ |
226 | skin = skin?skin: 'skin3' ; |
227 | |
228 | $( '#yxTreeCss' ).remove(); // 把旧样式去掉 |
229 | // 动态加入皮肤样式(CSS) |
230 | $( "script" ).each( function () { |
231 | if ( this .src.toString().match(/yx\.yxTree.*?js$/)) { |
232 | // 创建样式表 |
233 | $( "head" ).append( "<link rel=\"stylesheet\" type=\"text/css\" href=\"" + this .src.toString().replace(/yx\.yxTree.*?js$/, "" ) + "skin/" + skin + "/yxTree.css" + "\" id=\"yxTreeCss\" />" ); |
234 | } |
235 | }); |
236 | } |
237 |
238 | //从XML格式字符串里提取信息 |
239 | //source 数据源里的节点信息字符串(以后可以扩展对XML的支持) |
240 | //name 要提取的属性名 |
241 | yxTree.prototype.getAttribute = function (source, name){ |
242 | var reg = new RegExp( "(^|;|\\s)" + name + "\\s*:\\s*([^;]*)(\\s|;|$)" , "i" ); |
243 | if (reg.test(source)){ |
244 | return RegExp.$2.replace(/[\x0f]/g, ";" ).replace(/\'/g, "'" ); |
245 | } else { |
246 | return "" ; |
247 | } |
248 | }; |
249 |
250 | //为配合系统初始聚集某节点而写的函数, 得到某节点在数据源里的路径 |
251 | //sourceId 数据源里的节点 id |
252 | yxTree.prototype.getPath= function (sourceId) { |
253 | Array.prototype.indexOf = function (item) { |
254 | for ( var i=0; i< this .length; i++) { |
255 | if ( this [i]==item) return i; |
256 | } |
257 | return -1; |
258 | }; |
259 | var _d = this ._d, d = this .divider; |
260 | var A = new Array(), id=sourceId; A[0] = id; |
261 | while (id!= "0" && id!= "" ) { |
262 | var str = "(^|" +_d+ ")([^" +_d+d+ "]+" +d+ id + ")(" +_d+ "|$)" ; |
263 | if ( new RegExp(str).test( this .names)) { |
264 | id = RegExp.$2.substring(0, RegExp.$2.indexOf(d)); |
265 | if (A.indexOf(id)>-1) break ; |
266 | A[A.length] = id; |
267 | } else break ; |
268 | } |
269 | return A.reverse(); |
270 | }; |
271 |
272 | // 根据原来的 sourceId 取得node的实际 id(index) |
273 | yxTree.prototype.getRealId= function (sourceId) { |
274 | var node = this .getNodeBySid(sourceId); |
275 | return node.id; |
276 | } |
277 |
278 | // 根据原来的 sourceId 取得node |
279 | yxTree.prototype.getNodeBySid= function (sourceId) { |
280 | var path = this .getPath(sourceId); |
281 | var root = this .node[ "0" ], len = path.length; |
282 | for ( var i=1; i<len; i++) { |
283 | if (root.hasChild) { |
284 | for ( var k=0; k < root.childNodes.length; k++) { |
285 | if (root.childNodes[k].sourceId == path[i]) { |
286 | root = root.childNodes[k]; |
287 | break ; |
288 | } |
289 | } |
290 | } |
291 | } |
292 | return root; |
293 | }; |
294 |
295 | // 根据ID取得结点 |
296 | yxTree.prototype.getNode = function (id){ |
297 | return this .node[id]; |
298 | }; |
299 |
300 | //初始化数据源里的数据以便后面的快速检索 |
301 | yxTree.prototype.dataFormat = function () { |
302 | var a = new Array(); |
303 | for ( var id in this .nodes) { |
304 | a[a.length] = id; |
305 | } |
306 | this .names = a.join( this ._d + this ._d); |
307 | |
308 | this .totalNode = a.length; |
309 | a = null ; |
310 | }; |
[代码] css 代码
01 | .yxTree img.s {cursor:pointer;vertical-align:middle;} |
02 | .yxTree ul {padding:0; margin:0 0 0 17px;} |
03 | .yxTree li {list-style:none;padding:0;} |
04 | .yxTree .Closed ul {display:none;} |
05 | .yxTree .Child span.s {background:none;cursor: default ;} |
06 |
07 | .yxTree span.s {width:34px;height:18px; display:inline-block;} |
08 | .yxTree span.icon {} |
09 | .yxTree .Opened span.s {background:url(opened.gif) no-repeat 0 1px;cursor:pointer;} |
10 | .yxTree .Opened span.icon {} |
11 | .yxTree .Closed span.s {background:url(closed.gif) no-repeat 0 1px;cursor:pointer;} |
12 | .yxTree .Closed span.icon {} |
13 | .yxTree .Child span.s {background:url(child.gif) no-repeat 13px 2px;} |
14 | .yxTree .Child span.icon {} |
15 |
16 | .yxTree li a.focusNode{ font-size:14px; font-weight:600;} |