[Notice] Announcing the End of Demo Server [Read me]

fix CodeBrowser
@9371113c87af2c1f2cb79f8233a301ca847d8938
--- app/views/code/codeView.scala.html
+++ app/views/code/codeView.scala.html
... | ... | @@ -24,7 +24,7 @@ |
24 | 24 |
<button data-toggle="dropdown" class="btn dropdown-toggle bgwhite"><span class="caret"></span></button> |
25 | 25 |
<ul class="dropdown-menu"> |
26 | 26 |
@for(name <- branches){ |
27 |
- <li><a href="#!/@name">@name</a></li> |
|
27 |
+ <li><a href="#" class="branch-item">@name</a></li> |
|
28 | 28 |
} |
29 | 29 |
</ul> |
30 | 30 |
</div> |
... | ... | @@ -51,8 +51,7 @@ |
51 | 51 |
<td class="author"><strong>AUTHOR</strong></td> |
52 | 52 |
</tr> |
53 | 53 |
</thead> |
54 |
- <tbody class="tbody"> |
|
55 |
- </tbody> |
|
54 |
+ <tbody class="tbody contents"></tbody> |
|
56 | 55 |
</table> |
57 | 56 |
</div> |
58 | 57 |
@** // **@ |
... | ... | @@ -61,10 +60,10 @@ |
61 | 60 |
<div id="fileView" class="file-wrap cell" style="display:none;"> |
62 | 61 |
<div class="file-header nm"> |
63 | 62 |
<div id="fileInfo" class="file-info"> |
64 |
- <span class="commiter"></span> | |
|
65 |
- <span class="commitDate"></span> | |
|
66 |
- <span class="revision"></span> | |
|
67 |
- <span calss="commitMsg"></span> |
|
63 |
+ <span id="commiter" class="commiter"></span> | |
|
64 |
+ <span id="commitDate" class="commitDate"></span> | |
|
65 |
+ <span id="revisionNo" class="revision"></span> | |
|
66 |
+ <span id="commitMessage" calss="commitMsg"></span> |
|
68 | 67 |
</div> |
69 | 68 |
<a id="rawCode" class="btn-transparent btn-raw"><i class="ico ico-raw"></i>raw</a> |
70 | 69 |
</div> |
... | ... | @@ -103,9 +102,10 @@ |
103 | 102 |
<script type="text/javascript" src="/assets/javascripts/lib/moment.min.js"></script> |
104 | 103 |
<script type="text/javascript" src="/assets/javascripts/lib/moment.ko.js"></script> |
105 | 104 |
<!-- <script type="text/javascript" src="/assets/javascripts/service/hive.CodeBrowser.js"></script> --> |
105 |
+<script type="text/javascript" src="/assets/javascripts/lib/underscore.js"></script> |
|
106 | 106 |
<script type="text/javascript"> |
107 | 107 |
$(document).ready(function(){ |
108 |
- $hive.loadModule("code.Browser", { |
|
108 |
+ $hive.loadModule("code.Browser1", { |
|
109 | 109 |
"sProjectName": "@project.name" |
110 | 110 |
}); |
111 | 111 |
}); |
+++ public/javascripts/service/hive.code.Browser1.js
... | ... | @@ -0,0 +1,352 @@ |
1 | +/** | |
2 | + * @(#)hive.code.Browser1.js 2013.04.09 | |
3 | + * | |
4 | + * Copyright NHN Corporation. | |
5 | + * Released under the MIT license | |
6 | + * | |
7 | + * http://hive.dev.naver.com/license | |
8 | + */ | |
9 | + | |
10 | +(function(ns){ | |
11 | + | |
12 | + var oNS = $hive.createNamespace(ns); | |
13 | + oNS.container[oNS.name] = function(htOptions){ | |
14 | + | |
15 | + var project_name = htOptions.sProjectName; | |
16 | + | |
17 | + $(document).ready(function(){ | |
18 | + $(window).bind('hashchange', function(e){ | |
19 | + _updateDynaTree(); | |
20 | + | |
21 | + //대기 표시 한다. | |
22 | + //여기서 요청을 보내고 | |
23 | + var path = getHash().replace(/^#/, ""); | |
24 | + var branch = encodeURIComponent($("#selected-branch").text()); | |
25 | + | |
26 | + $.ajax("code/" + branch + "/!" + path, { | |
27 | + datatype : "json", | |
28 | + success : function(data, textStatus, jqXHR){ | |
29 | + updateBreadcrumbs(path); | |
30 | + switch(data.type){ | |
31 | + case "file" : | |
32 | + handleFile(data); | |
33 | + break; | |
34 | + case "folder" : | |
35 | + handleFolder(data); | |
36 | + break; | |
37 | + } | |
38 | + }, | |
39 | + error : function(){ | |
40 | + $("#codeError").show(); | |
41 | + } | |
42 | + }); | |
43 | + | |
44 | + function handleFile(data){ | |
45 | + //파일을 표시한다. | |
46 | + $("#commiter").text(data.author); | |
47 | + if( data.hasOwnProperty("msg") ) $("#commitMessage").text(data.msg); | |
48 | + if( data.hasOwnProperty("revisionNo") ) $("#revisionNo").text("Revision#: " + data.revisionNo); | |
49 | + $("#commitDate").text(moment(new Date(data.date)).fromNow()); | |
50 | + $("pre").text(data.data); | |
51 | + $("#rawCode").attr("href", "rawcode"+path);//TODO 현재 동작하지 않음. | |
52 | + | |
53 | + $("#fileList").hide(); | |
54 | + $("#fileView").show(); | |
55 | + $("pre").highlight(); | |
56 | + } | |
57 | + | |
58 | + function handleFolder(data){ | |
59 | + data.data = sortData(data.data); | |
60 | + | |
61 | + //폴더내용을 리스팅 한다. | |
62 | + $("#commiter").text(data.author); | |
63 | + if( data.hasOwnProperty("msg") ) $("#commitMessage").text(data.msg); | |
64 | + if( data.hasOwnProperty("revisionNo") ) $("#revisionNo").text("Revision #: " + data.revisionNo); | |
65 | + $("#commitDate").text(data.date); | |
66 | + | |
67 | + $(".contents").children().remove(); | |
68 | + | |
69 | + var info, tablerow; | |
70 | + for(var name in data.data){ | |
71 | + info = data.data[name]; | |
72 | + tablerow = makeTableRow(name, info.msg, info.createdDate, info.author); | |
73 | + $(".contents").append(tablerow); | |
74 | + } | |
75 | + | |
76 | + $("#fileList").show(); | |
77 | + $("#fileView").hide(); | |
78 | + } | |
79 | + | |
80 | + function sortData(target){ | |
81 | + result = []; | |
82 | + | |
83 | + /** case-insensitive sort **/ | |
84 | + var aTmp = []; | |
85 | + for(var key in target){ | |
86 | + aTmp.push(key); | |
87 | + } | |
88 | + aTmp.sort(function(a,b){ | |
89 | + if(a.toLowerCase() < b.toLowerCase()) { return -1; } | |
90 | + if(a.toLowerCase() > b.toLowerCase()) { return 1; } | |
91 | + return 0; | |
92 | + }); | |
93 | + | |
94 | + var ht = {}; | |
95 | + aTmp.forEach(function(sKey){ | |
96 | + ht[sKey] = target[sKey]; | |
97 | + }); | |
98 | + /** **/ | |
99 | + | |
100 | + _.each(ht, function(value, key, list){ | |
101 | + ht[key].name = key; | |
102 | + result.push(ht[key]); | |
103 | + }); | |
104 | + | |
105 | + result = _.sortBy(result, function(elm){ | |
106 | + return -(elm.type === "folder"); | |
107 | + }); | |
108 | + | |
109 | + var htResult = {}; | |
110 | + result.forEach(function(o){ | |
111 | + htResult[o.name] = o; | |
112 | + }); | |
113 | + | |
114 | + try { | |
115 | + return htResult; | |
116 | + } finally { | |
117 | + aTmp = ht = null; | |
118 | + } | |
119 | + } | |
120 | + | |
121 | + function makeTableRow(name, message, date, author){ | |
122 | + if (message.length > 70){ | |
123 | + message = message.substr(0, 70) + "..."; | |
124 | + } | |
125 | + | |
126 | + return $("<tr>") | |
127 | + .append( | |
128 | + $("<td>").append( | |
129 | + $("<a>").text(name).attr("href", "#" + (path !== "/" ? path : "") + "/" +name) | |
130 | + ).addClass("filename") | |
131 | + ) | |
132 | + .append($("<td>").text(message).addClass("message")) | |
133 | + .append($("<td>").text(moment(new Date(date)).fromNow()).addClass("date")) | |
134 | + // .append($("<td>").text(author).addClass("author")) | |
135 | + .append($('<td class="author"><a href="/'+ author+'"><img src="/assets/images/default-avatar-34.png" alt="avatar" class="img-rounded"></a></td>')); | |
136 | + } | |
137 | + | |
138 | + function updateBreadcrumbs(path){ | |
139 | + var $breadcrumbs = $("#breadcrumbs"); | |
140 | + $($breadcrumbs).html('<a href="#/">'+project_name+'</a>'); | |
141 | + | |
142 | + var names = path.split("/"); | |
143 | + var str = "#" | |
144 | + for(var i = 1; i < names.length; i++){ | |
145 | + var name = names[i]; | |
146 | + str += "/" + name; | |
147 | + $breadcrumbs.append("/"); | |
148 | + $("<a>").text(name).attr("href", str).appendTo($breadcrumbs); | |
149 | + } | |
150 | + } | |
151 | + }); | |
152 | + | |
153 | + if(!$("#selected-branch").text()){ | |
154 | + $("#selected-branch").text('HEAD'); | |
155 | + } | |
156 | + $(window).trigger('hashchange'); | |
157 | + }); | |
158 | + | |
159 | + function getHash() { | |
160 | + return document.location.hash; | |
161 | + } | |
162 | + | |
163 | + function setHash(hash) { | |
164 | + return document.location.hash = hash; | |
165 | + } | |
166 | + | |
167 | + function standizePath(path) { | |
168 | + return "/" + path.split("/").filter(isEmpty).join("/"); | |
169 | + function isEmpty(data) { | |
170 | + if (data == "") { | |
171 | + return false; | |
172 | + } else { | |
173 | + return true; | |
174 | + } | |
175 | + } | |
176 | + } | |
177 | + | |
178 | + $(".branch-item").click(function(ev) { | |
179 | + $("#selected-branch").text($(this).text()); | |
180 | + $(window).trigger('hashchange'); | |
181 | + }); | |
182 | + | |
183 | + // adaptorForDynatree adaptor function is used for existed function | |
184 | + // Also, it pass the below tests | |
185 | + // | |
186 | + // it("file & folder combine", function() { | |
187 | + // //Given | |
188 | + // var target = { | |
189 | + // "attachment": { | |
190 | + // "type": "folder", | |
191 | + // "msg": "add folders", | |
192 | + // "author": "doortts", | |
193 | + // "date": "Mon Jan 28 14:21:07 KST 2013" | |
194 | + // }, | |
195 | + // "favicon.ico": { | |
196 | + // "type": "file", | |
197 | + // "msg": "add folders", | |
198 | + // "author": "doortts", | |
199 | + // "date": "Mon Jan 28 14:21:07 KST 2013" | |
200 | + // } | |
201 | + // }; | |
202 | + // var expected = [ | |
203 | + // {title: "attachment", isFolder: true, isLazy: true}, | |
204 | + // {title: "favicon.ico"} | |
205 | + // ]; | |
206 | + // //When | |
207 | + // var result = adaptorForDynatree(target); | |
208 | + // //Then | |
209 | + // assert.deepEqual(result, expected); | |
210 | + // }); | |
211 | + | |
212 | + var result = []; | |
213 | + | |
214 | + function adaptorForDynatree(target){ | |
215 | + result = []; | |
216 | + | |
217 | + /** case-insensitive sort **/ | |
218 | + var aTmp = []; | |
219 | + for(var key in target){ | |
220 | + aTmp.push(key); | |
221 | + } | |
222 | + aTmp.sort(function(a,b){ | |
223 | + if(a.toLowerCase() < b.toLowerCase()) { return -1; } | |
224 | + if(a.toLowerCase() > b.toLowerCase()) { return 1; } | |
225 | + return 0; | |
226 | + }); | |
227 | + var ht = {}; | |
228 | + aTmp.forEach(function(sKey){ | |
229 | + ht[sKey] = target[sKey]; | |
230 | + }); | |
231 | + /** **/ | |
232 | + | |
233 | + _.each(ht, function(value, key, list){ | |
234 | + if(value.type === "folder") { | |
235 | + result.push({ title: key, isFolder: true, isLazy: true}); | |
236 | + } else { | |
237 | + result.push({ title: key}); | |
238 | + } | |
239 | + }); | |
240 | + | |
241 | + return _.sortBy(result, function(elm){ | |
242 | + return -elm.hasOwnProperty("isFolder"); | |
243 | + }); | |
244 | + } | |
245 | + | |
246 | + function findTreeNode(path){ | |
247 | + var root = $("#folderList").dynatree("getRoot"); | |
248 | + var nodes = path.split("/"); // "a/b/c" => a, b, c | |
249 | + var currentNode = root; | |
250 | + var searchTarget; | |
251 | + | |
252 | + for(var idx in nodes){ | |
253 | + searchTarget = currentNode.getChildren(); | |
254 | + for( var jdx in searchTarget){ | |
255 | + if ( searchTarget[jdx].data.title === nodes[idx] ) { | |
256 | + currentNode = searchTarget[jdx]; | |
257 | + currentNode.expand(); | |
258 | + break; | |
259 | + } | |
260 | + } | |
261 | + } | |
262 | + } | |
263 | + | |
264 | + // Traverse the path of selected tree item | |
265 | + function getTreePath(node){ | |
266 | + var path = ""; | |
267 | + if( node.getParent() && node.getParent().data.title !== null ){ | |
268 | + path = getTreePath(node.getParent()) + "/" + node.data.title; | |
269 | + } else { | |
270 | + path = node.data.title; | |
271 | + } | |
272 | + return path; | |
273 | + } | |
274 | + | |
275 | + // initial path loading | |
276 | + var rootPath = ""; | |
277 | + var treeSelectorId = "#folderList"; | |
278 | + | |
279 | + /* | |
280 | + $(function(){ | |
281 | + var path = getHash().replace(/^#/, ""); | |
282 | + var branch = encodeURIComponent($("#selected-branch").text()); | |
283 | + rootPath = "code/" + branch + "/!/"; | |
284 | + $.ajax({ | |
285 | + url: rootPath, | |
286 | + success: function(result, textStatus){ | |
287 | + treeInit(adaptorForDynatree(result.data)); | |
288 | + findTreeNode(path.substr(1)); // path.substr(1) "/a/b/c" => "a/b/c" | |
289 | + } | |
290 | + }); | |
291 | + }); | |
292 | + */ | |
293 | + | |
294 | + function _updateDynaTree(){ | |
295 | +// $("#folderList").dynatree("getRoot").removeChildren(true); | |
296 | + | |
297 | + var path = getHash().replace(/^#/, ""); | |
298 | + var branch = encodeURIComponent($("#selected-branch").text()); | |
299 | + rootPath = "code/" + branch + "/!/"; | |
300 | + $.ajax({ | |
301 | + url: rootPath, | |
302 | + success: function(result, textStatus){ | |
303 | + treeInit(adaptorForDynatree(result.data)); | |
304 | + findTreeNode(path.substr(1)); // path.substr(1) "/a/b/c" => "a/b/c" | |
305 | + } | |
306 | + }); | |
307 | + } | |
308 | + _updateDynaTree(); | |
309 | + | |
310 | + // DynaTree Init function | |
311 | + // see: http://wwwendt.de/tech/dynatree/doc/dynatree-doc.html | |
312 | + function treeInit(initData){ | |
313 | + $(treeSelectorId).dynatree({ | |
314 | + fx: { height: "toggle", duration: 200 }, | |
315 | + autoFocus: false, | |
316 | + isLazy: true, | |
317 | + onLazyRead: function(node){ | |
318 | + $.ajax({ | |
319 | + url: rootPath + getTreePath(node), | |
320 | + success: function(result, textStatus) { | |
321 | + // Called after nodes have been created and the waiting icon was removed. | |
322 | + // 'this' is the options for this Ajax request | |
323 | + if(result){ | |
324 | + node.setLazyNodeStatus(DTNodeStatus_Ok); | |
325 | + node.addChild(adaptorForDynatree(result.data)); | |
326 | + }else{ | |
327 | + // Server returned an error condition: set node status accordingly | |
328 | + node.setLazyNodeStatus(DTNodeStatus_Error, { | |
329 | + tooltip: "Loading failed", | |
330 | + info: result | |
331 | + }); | |
332 | + } | |
333 | + }, | |
334 | + error: function(node, XMLHttpRequest, textStatus, errorThrown) { | |
335 | + // Called on error, after error icon was created. | |
336 | + console.log(node); | |
337 | + }, | |
338 | + cache: false // Append random '_' argument to url to prevent caching. | |
339 | + }); | |
340 | + }, | |
341 | + onActivate: function(node) { | |
342 | + // A DynaTreeNode object is passed to the activation handler | |
343 | + // Note: we also get this event, if persistence is on, and the page is reloaded. | |
344 | + window.location = "#/" + getTreePath(node); | |
345 | + }, | |
346 | + title: "/", | |
347 | + children: initData, | |
348 | + debugLevel: 0 | |
349 | + }); | |
350 | + } | |
351 | + }; | |
352 | +})("hive.code.Browser1");(No newline at end of file) |
Add a comment
Delete comment
Once you delete this comment, you won't be able to recover it. Are you sure you want to delete this comment?