OSDN Git Service

git-svn-id: https://svn.sourceforge.jp/svnroot/nucleus-jp/plugin@1020 1ca29b6e-896d...
[nucleus-jp/nucleus-plugins.git] / NP_TrackBack / trunk / trackback / js / rico / ricoTree.js
1 //  Rico Tree Control\r
2 //  by Matt Brown\r
3 //  Oct 2006\r
4 //  email: dowdybrown@yahoo.com\r
5 \r
6 //  Requires prototype.js and ricoCommon.js\r
7 \r
8 // each node in nodeIndex is an Array with 6+n positions\r
9 //  node[0] is 0/1 when the node is closed/open\r
10 //  node[1] is 0/1 when the folder is closed/open\r
11 //  node[2] is 1 if the node is a leaf node\r
12 //  node[3] is the node id\r
13 //  node[4] is the node description\r
14 //  node[5] is 1 when the node is selectable, 0 otherwise\r
15 //  node[6]...node[6+n] are the child nodes\r
16 \r
17 Rico.TreeControl = Class.create();\r
18 \r
19 Rico.TreeControl.prototype = {\r
20 \r
21   initialize: function(id,url,options) {\r
22     Object.extend(this, new Rico.Popup({ignoreClicks:true}));\r
23     Object.extend(this.options, {\r
24       nodeIdDisplay:'none',   // first, last, tooltip, or none\r
25       showCheckBox: false,\r
26       showFolders: false,\r
27       showPlusMinus: true,\r
28       defaultAction: this.nodeClick.bindAsEventListener(this),\r
29       height: '300px',\r
30       width: '300px',\r
31       leafIcon: Rico.imgDir+'doc.gif'\r
32     });\r
33     Object.extend(this.options, options || {});\r
34     this.img=[];\r
35     this.FirstChildNode=6;\r
36     this.nodeIndex={};\r
37     this.nodeCount=0;\r
38     this.foldersTree=0;\r
39     this.timeOutId=0;\r
40     this.id=id;\r
41     this.dataSource=url;\r
42     this.close=this.closePopup;\r
43   },\r
44 \r
45   atLoad : function() {\r
46     var imgsrc = new Array("node.gif","nodelast.gif","folderopen.gif","folderclosed.gif");\r
47     for (i=0;i<imgsrc.length;i++) {\r
48       this.img[i] = new Image\r
49       this.img[i].src = Rico.imgDir+imgsrc[i]\r
50       //this.img[i].src = Rico.imgDir + imgsrc[i]\r
51     }\r
52     this.treeDiv=document.createElement("div");\r
53     this.treeDiv.id=this.id;\r
54     this.treeDiv.className='ricoTree';\r
55     this.treeDiv.style.height=this.options.height;\r
56     this.treeDiv.style.width=this.options.width;\r
57     this.container=document.createElement("div");\r
58     this.container.style.display="none"\r
59     this.container.className='ricoTreeContainer';\r
60     this.container.appendChild(this.treeDiv);\r
61     document.body.appendChild(this.container);\r
62     this.setDiv(this.container);\r
63     this.close();\r
64   },\r
65 \r
66   // Building the data in the tree\r
67   open: function() {\r
68     this.openPopup();\r
69     if (this.nodeCount==0) this.loadXMLDoc();\r
70   },\r
71 \r
72   loadXMLDoc: function(branchPin) {\r
73     var parms="id="+this.id;\r
74     if (branchPin) parms+="&Parent="+branchPin;\r
75     Rico.writeDebugMsg('Tree loadXMLDoc:\n'+parms+'\n'+this.dataSource);\r
76     new Ajax.Request(this.dataSource, {parameters:parms,method:'get',onComplete:this.processResponse.bind(this)});\r
77   },\r
78 \r
79   processResponse: function(request) {\r
80     var response = request.responseXML.getElementsByTagName("ajax-response");\r
81     if (response == null || response.length != 1) return;\r
82     var rowsElement = response[0].getElementsByTagName('rows')[0];\r
83     var trs = rowsElement.getElementsByTagName("tr");\r
84     //alert('processResponse: '+trs.length);\r
85     for ( var i=0 ; i < trs.length; i++ ) {\r
86       var cells = trs[i].getElementsByTagName("td");\r
87       if (cells.length != 5) continue;\r
88       // cells[0]=parent node id\r
89       // cells[1]=node id\r
90       // cells[2]=description\r
91       // cells[3]=L/zero (leaf), C/non-zero (container)\r
92       // cells[4]= 0->not selectable, 1->selectable (use default action), otherwise the node is selectable and cells[4] contains the action\r
93       var content=[];\r
94       for (var j=0; j<cells.length; j++)\r
95         content[j]=this.getContent(cells[j]);\r
96         //content[j]=RicoUtil.getContentAsString(cells[j]);\r
97       var node=this.addNode(content[3],content[1],content[2],content[4]);\r
98       if (this.foldersTree==0) {\r
99         this.foldersTree = node;\r
100         node[0]=1;\r
101         node[1]=1;\r
102       } else {\r
103         var parentNode=this.nodeIndex[content[0]]\r
104         if (typeof parentNode=='undefined')\r
105           alert('ERROR!\nReceived invalid response from server - could not find parent in existing tree:\n'+content[0]);\r
106         else\r
107           parentNode.push(node);\r
108       }\r
109     }\r
110     if (this.nodeCount==1 && node[2])\r
111       this.loadXMLDoc(node[3]);\r
112     else\r
113       this.redrawTree();\r
114   },\r
115 \r
116   getContent: function(cell) {\r
117     if (cell.innerHTML) return cell.innerHTML;\r
118     switch (cell.childNodes.length) {\r
119       case 0:  return "";\r
120       case 1:  return cell.firstChild.nodeValue;\r
121       default: return cell.childNodes[1].nodeValue;\r
122     }\r
123   },\r
124 \r
125   // create new node\r
126   // NodeType is "C" or non-zero (container), or "L" or zero (leaf)\r
127   // id is the unique identifier for the node\r
128   // desc is the text displayed to the user\r
129   addNode: function(NodeType,id,desc,selectable) {\r
130     var arrayAux\r
131     //alert("addNode: " + desc + " (" + selectable + ")")\r
132     arrayAux = new Array\r
133     arrayAux[0] = 0\r
134     arrayAux[1] = 0\r
135     arrayAux[2] = (NodeType=='0' || NodeType.toUpperCase()=='L' ? 0 : 1)\r
136     arrayAux[3] = id\r
137     arrayAux[4] = desc\r
138     arrayAux[5] = parseInt(selectable);\r
139     this.nodeIndex[id]=arrayAux\r
140     this.nodeCount++;\r
141   \r
142     return arrayAux\r
143   },\r
144 \r
145   RemoveAllChildren: function(obj) {\r
146         while (obj.hasChildNodes()) {\r
147                 this.RemoveAllChildren(obj.childNodes[0])\r
148                 obj.removeChild(obj.childNodes[0])\r
149         }\r
150   },\r
151 \r
152   redrawTree: function() {\r
153     //alert('redrawTree');\r
154     this.RemoveAllChildren(this.treeDiv)\r
155     this.redrawNode(this.foldersTree, 0, 1, [])\r
156   },\r
157 \r
158   DisplayImages: function(row,arNames) {\r
159     var i,img,td\r
160     for(i=0;i<arNames.length;i++) {\r
161       img = document.createElement("img")\r
162       img.src=Rico.imgDir+arNames[i] + ".gif"\r
163       td=row.insertCell(-1)\r
164       td.appendChild(img)\r
165     }\r
166   },\r
167 \r
168   redrawNode: function(foldersNode, level, lastNode, leftSide) {\r
169     var tab,row\r
170     //alert("redrawNode at level " + level + " (" + foldersNode[3] + ")")\r
171     \r
172     tab = document.createElement("table")\r
173     tab.border=0\r
174     tab.cellSpacing=0\r
175     tab.cellPadding=0\r
176     row=tab.insertRow(0)\r
177     this.DisplayImages(row,leftSide)\r
178     var newLeft=leftSide.slice(0);\r
179     if (level>0) {\r
180       var suffix=lastNode ? 'last' : '';\r
181       if (this.options.showPlusMinus && foldersNode[2])\r
182         this.showPlusMinus(row.insertCell(-1),foldersNode,suffix);\r
183       else\r
184         this.NodeImage(row.insertCell(-1),suffix)\r
185       newLeft.push(lastNode ? "nodeblank" : "nodeline")\r
186     }\r
187     if (this.options.showFolders)\r
188       this.showFolders(row.insertCell(-1),foldersNode);\r
189     if (this.options.showCheckBox && foldersNode[5])\r
190       this.showCheckBox(row.insertCell(-1),foldersNode);\r
191     this.displayLabel(row,foldersNode)\r
192     this.treeDiv.appendChild(tab)\r
193   \r
194     if (foldersNode.length > this.FirstChildNode && foldersNode[0]) {\r
195       //there are sub-nodes and the folder is open\r
196       for (var i=this.FirstChildNode; i<foldersNode.length;i++)\r
197         this.redrawNode(foldersNode[i], level+1, (i==foldersNode.length-1 ? 1 : 0), newLeft)\r
198     }\r
199   },\r
200 \r
201   NodeImage: function(td, suffix) {\r
202     var img\r
203     img = document.createElement("img")\r
204     img.src=Rico.imgDir+"node"+suffix+".gif"\r
205     td.appendChild(img)\r
206   },\r
207 \r
208 \r
209   showPlusMinus: function(td,foldersNode,suffix) {\r
210     var img = document.createElement("img")\r
211     img.name=foldersNode[3];\r
212     img.style.cursor='pointer';\r
213     if (foldersNode.length > this.FirstChildNode)\r
214       img.onclick=this.openBranch.bindAsEventListener(this);\r
215     else\r
216       img.onclick=this.getChildren.bindAsEventListener(this);\r
217     var prefix=foldersNode[1] ? "nodem" : "nodep"\r
218     img.src=Rico.imgDir+prefix+suffix+".gif";\r
219     td.appendChild(img)\r
220   },\r
221 \r
222   showFolders: function(td,foldersNode) {\r
223     var img = document.createElement("img")\r
224     if (!foldersNode[2]) {\r
225       img.src=this.options.leafIcon;\r
226     } else {\r
227       img.name=foldersNode[3];\r
228       img.style.cursor='pointer';\r
229       if (foldersNode.length > this.FirstChildNode)\r
230         img.onclick=this.openBranch.bindAsEventListener(this);\r
231       else\r
232         img.onclick=this.getChildren.bindAsEventListener(this);\r
233       img.src=Rico.imgDir+(foldersNode[1] ? "folderopen.gif" : "folderclosed.gif");\r
234     }\r
235     td.appendChild(img)\r
236   },\r
237 \r
238   showCheckBox: function(td,foldersNode) {\r
239     var inp=document.createElement("input")\r
240     inp.type="checkbox"\r
241     inp.name=foldersNode[3]\r
242     td.appendChild(inp)\r
243   },\r
244 \r
245   displayLabel: function(row,foldersNode) {\r
246     if (foldersNode[5]) {\r
247       var span=document.createElement('a');\r
248       span.href='#';\r
249       span.onclick=this.options.defaultAction;\r
250     } else {\r
251       var span=document.createElement('p');\r
252     }\r
253     span.id=this.id+"__"+foldersNode[3];\r
254     var desc=foldersNode[4];\r
255     switch (this.options.nodeIdDisplay) {\r
256       case 'last': desc+=' ('+foldersNode[3]+')'; break;\r
257       case 'first': desc=foldersNode[3]+' - '+desc; break;\r
258       case 'tooltip': span.title=foldersNode[3]; break;\r
259     }\r
260         span.appendChild(document.createTextNode(desc))\r
261     var td=row.insertCell(-1)\r
262     td.appendChild(span)\r
263   },\r
264 \r
265   //when a parent is closed all children also are\r
266   closeFolders: function(foldersNode) {\r
267     var i=0\r
268     if (foldersNode[2]) {\r
269       for (i=this.FirstChildNode; i< foldersNode.length; i++)\r
270         this.closeFolders(foldersNode[i])\r
271     }\r
272     foldersNode[0] = 0\r
273     foldersNode[1] = 0\r
274   },\r
275   \r
276   nodeClick: function(e) {\r
277     var node=Event.element(e);\r
278     if (this.returnValue) {\r
279       var v=node.id;\r
280       var i=v.indexOf('__');\r
281       if (i>=0) v=v.substr(i+2);\r
282       this.returnValue(v,node.innerHTML);\r
283     }\r
284     this.close();\r
285   },\r
286 \r
287   //recurse over the tree structure\r
288   //called by openbranch\r
289   clickOnFolderRec: function(foldersNode, folderName) {\r
290     var i=0\r
291     if (foldersNode[3] == folderName) {\r
292       if (foldersNode[0]) {\r
293         this.closeFolders(foldersNode)\r
294       } else {\r
295         foldersNode[0] = 1\r
296         foldersNode[1] = 1\r
297       }\r
298     } else if (foldersNode[2]) {\r
299       for (i=this.FirstChildNode; i< foldersNode.length; i++)\r
300         this.clickOnFolderRec(foldersNode[i], folderName)\r
301     }\r
302   },\r
303 \r
304   openBranch: function(e) {\r
305     var node=Event.element(e);\r
306     this.clickOnFolderRec(this.foldersTree, node.name)\r
307     this.timeOutId = setTimeout(this.redrawTree.bind(this),100)\r
308   },\r
309 \r
310   getChildren: function(e) {\r
311     var node=Event.element(e);\r
312     this.loadXMLDoc(node.name)\r
313     this.openBranch(e)\r
314   }\r
315 \r
316 }\r
317 \r
318 Rico.includeLoaded('ricoTree.js');