[Notice] Announcing the End of Demo Server [Read me]
Jihan Kim 2013-04-09
fix CodeBrowser
@9371113c87af2c1f2cb79f8233a301ca847d8938
app/views/code/codeView.scala.html
--- app/views/code/codeView.scala.html
+++ app/views/code/codeView.scala.html
@@ -24,7 +24,7 @@
 				<button data-toggle="dropdown" class="btn dropdown-toggle bgwhite"><span class="caret"></span></button>
 				<ul class="dropdown-menu">
 					@for(name <- branches){
-					<li><a href="#!/@name">@name</a></li>
+					<li><a href="#" class="branch-item">@name</a></li>
 					}
 				</ul>
 			</div>
@@ -51,8 +51,7 @@
 							<td class="author"><strong>AUTHOR</strong></td>
 						</tr>
 					</thead>
-					<tbody class="tbody">
-					</tbody>
+					<tbody class="tbody contents"></tbody>
 				</table>
 			</div>
 			@** // **@
@@ -61,10 +60,10 @@
 			<div id="fileView" class="file-wrap cell" style="display:none;">
 				<div class="file-header nm">
 					<div id="fileInfo" class="file-info">
-						<span class="commiter"></span> | 
-						<span class="commitDate"></span> | 
-						<span class="revision"></span> |
-						<span calss="commitMsg"></span>
+						<span id="commiter" class="commiter"></span> | 
+						<span id="commitDate" class="commitDate"></span> | 
+						<span id="revisionNo" class="revision"></span> |
+						<span id="commitMessage" calss="commitMsg"></span>
 					</div>
 					<a id="rawCode" class="btn-transparent btn-raw"><i class="ico ico-raw"></i>raw</a>
 				</div>
@@ -103,9 +102,10 @@
 <script type="text/javascript" src="/assets/javascripts/lib/moment.min.js"></script>
 <script type="text/javascript" src="/assets/javascripts/lib/moment.ko.js"></script>
 <!-- <script type="text/javascript" src="/assets/javascripts/service/hive.CodeBrowser.js"></script> -->
+<script type="text/javascript" src="/assets/javascripts/lib/underscore.js"></script>
 <script type="text/javascript">
 	$(document).ready(function(){
-		$hive.loadModule("code.Browser", {
+		$hive.loadModule("code.Browser1", {
 			"sProjectName": "@project.name"
 		});
 	});
 
public/javascripts/service/hive.code.Browser1.js (added)
+++ public/javascripts/service/hive.code.Browser1.js
@@ -0,0 +1,352 @@
+/**
+ * @(#)hive.code.Browser1.js 2013.04.09
+ *
+ * Copyright NHN Corporation.
+ * Released under the MIT license
+ * 
+ * http://hive.dev.naver.com/license
+ */
+
+(function(ns){
+
+	var oNS = $hive.createNamespace(ns);
+	oNS.container[oNS.name] = function(htOptions){
+
+		var project_name = htOptions.sProjectName;
+	
+		$(document).ready(function(){
+			$(window).bind('hashchange', function(e){
+				_updateDynaTree();
+				
+		        //대기 표시 한다.
+		        //여기서 요청을 보내고
+		        var path = getHash().replace(/^#/, "");
+		        var branch = encodeURIComponent($("#selected-branch").text());
+		
+		        $.ajax("code/" + branch + "/!" + path, {
+		          datatype : "json",
+		          success : function(data, textStatus, jqXHR){
+		            updateBreadcrumbs(path);
+		            switch(data.type){
+		              case "file" :
+		                  handleFile(data);
+		                break;
+		              case "folder" :
+		                  handleFolder(data);
+		                break;
+		            }
+		          },
+		          error : function(){
+		            $("#codeError").show();
+		          }
+		        });
+		        
+		        function handleFile(data){
+		            //파일을 표시한다.
+		            $("#commiter").text(data.author);
+		            if( data.hasOwnProperty("msg") ) $("#commitMessage").text(data.msg);
+		            if( data.hasOwnProperty("revisionNo") ) $("#revisionNo").text("Revision#: " + data.revisionNo);
+		            $("#commitDate").text(moment(new Date(data.date)).fromNow());
+		            $("pre").text(data.data);
+		            $("#rawCode").attr("href", "rawcode"+path);//TODO 현재 동작하지 않음.
+		            
+		            $("#fileList").hide();
+		            $("#fileView").show();
+		            $("pre").highlight();
+		        }
+		        
+		        function handleFolder(data){
+		        	data.data = sortData(data.data);
+		        	
+		            //폴더내용을 리스팅 한다.
+		            $("#commiter").text(data.author);
+		            if( data.hasOwnProperty("msg") ) $("#commitMessage").text(data.msg);
+		            if( data.hasOwnProperty("revisionNo") ) $("#revisionNo").text("Revision #: " + data.revisionNo);
+		            $("#commitDate").text(data.date);
+		
+		            $(".contents").children().remove();
+		
+		            var info, tablerow;
+		            for(var name in data.data){
+		            	info = data.data[name];
+		              	tablerow = makeTableRow(name, info.msg, info.createdDate, info.author);
+		              	$(".contents").append(tablerow);
+		            }
+		
+		            $("#fileList").show();
+		            $("#fileView").hide();
+		        }
+		        
+				function sortData(target){
+				    result = [];
+				    
+				    /** case-insensitive sort **/
+				    var aTmp = [];
+				    for(var key in target){
+				    	aTmp.push(key);
+				    }
+				    aTmp.sort(function(a,b){
+				    	if(a.toLowerCase() < b.toLowerCase()) { return -1; }
+				    	if(a.toLowerCase() > b.toLowerCase()) { return 1; }
+				    	return 0;
+				    });
+				    
+				    var ht = {};
+				    aTmp.forEach(function(sKey){
+				    	ht[sKey] = target[sKey];
+				    });
+				    /** **/
+				    
+				    _.each(ht, function(value, key, list){
+				    	ht[key].name = key;
+				        result.push(ht[key]);
+				    });
+				    
+				    result = _.sortBy(result, function(elm){
+				        return -(elm.type === "folder");
+				    });
+				    
+				    var htResult = {};
+				    result.forEach(function(o){
+				    	htResult[o.name] = o;
+				    });
+				    
+				    try {
+				    	return htResult;
+				    } finally {
+				    	aTmp = ht = null;
+				    }
+				}
+				
+		        function makeTableRow(name, message, date, author){
+		          if (message.length > 70){
+		            message = message.substr(0, 70) + "...";
+		          }
+
+		          return $("<tr>")
+		              .append(
+		                  $("<td>").append(
+		                      $("<a>").text(name).attr("href", "#" + (path !== "/" ? path : "") + "/" +name)
+		                    ).addClass("filename")
+		                  )
+		              .append($("<td>").text(message).addClass("message"))
+		              .append($("<td>").text(moment(new Date(date)).fromNow()).addClass("date"))
+		              // .append($("<td>").text(author).addClass("author"))
+		              .append($('<td class="author"><a href="/'+ author+'"><img src="/assets/images/default-avatar-34.png" alt="avatar" class="img-rounded"></a></td>'));
+		        }
+		        
+		        function updateBreadcrumbs(path){
+		          var $breadcrumbs = $("#breadcrumbs");
+		          $($breadcrumbs).html('<a href="#/">'+project_name+'</a>');
+		                      
+		          var names = path.split("/");
+		          var str = "#"
+		          for(var i = 1; i < names.length; i++){
+		            var name = names[i];
+		            str += "/" + name;
+		            $breadcrumbs.append("/");
+		            $("<a>").text(name).attr("href", str).appendTo($breadcrumbs);
+		          }
+		        }
+		      });
+		
+		      if(!$("#selected-branch").text()){
+		    	  $("#selected-branch").text('HEAD');
+		      }
+		      $(window).trigger('hashchange');
+		});
+		
+		function getHash() {
+			return document.location.hash;
+		}
+		
+		function setHash(hash) {
+			return document.location.hash = hash;
+		}
+		
+		function standizePath(path) {
+			return "/" + path.split("/").filter(isEmpty).join("/");
+			function isEmpty(data) {
+				if (data == "") {
+					return false;
+				} else {
+					return true;
+				}
+			}
+		}
+		
+		$(".branch-item").click(function(ev) {
+			$("#selected-branch").text($(this).text());
+			$(window).trigger('hashchange');
+		});
+		
+		// adaptorForDynatree adaptor function is used for existed function
+		// Also, it pass the below tests
+		//
+		// it("file & folder combine", function() {
+		//     //Given
+		//     var target = {
+		//         "attachment": {
+		//             "type": "folder",
+		//             "msg": "add folders",
+		//             "author": "doortts",
+		//             "date": "Mon Jan 28 14:21:07 KST 2013"
+		//         },
+		//         "favicon.ico": {
+		//             "type": "file",
+		//             "msg": "add folders",
+		//             "author": "doortts",
+		//             "date": "Mon Jan 28 14:21:07 KST 2013"
+		//         }
+		//     };
+		//     var expected = [
+		//         {title: "attachment", isFolder: true, isLazy: true},
+		//         {title: "favicon.ico"}
+		//     ];
+		//     //When
+		//     var result = adaptorForDynatree(target);
+		//     //Then
+		//     assert.deepEqual(result, expected);
+		// });
+		
+		var result = [];
+			
+		function adaptorForDynatree(target){
+		    result = [];
+		    
+		    /** case-insensitive sort **/
+		    var aTmp = [];
+		    for(var key in target){
+		    	aTmp.push(key);
+		    }
+		    aTmp.sort(function(a,b){
+		    	if(a.toLowerCase() < b.toLowerCase()) { return -1; }
+		    	if(a.toLowerCase() > b.toLowerCase()) { return 1; }
+		    	return 0;
+		    });
+		    var ht = {};
+		    aTmp.forEach(function(sKey){
+		    	ht[sKey] = target[sKey];
+		    });
+		    /** **/
+		    
+		    _.each(ht, function(value, key, list){
+		        if(value.type === "folder") {
+		            result.push({ title: key, isFolder: true, isLazy: true});
+		        } else {
+		            result.push({ title: key});
+		        }
+		    });
+		    
+		    return _.sortBy(result, function(elm){
+		        return -elm.hasOwnProperty("isFolder");
+		    });
+		}
+		
+		function findTreeNode(path){
+		    var root = $("#folderList").dynatree("getRoot");
+		    var nodes = path.split("/");  // "a/b/c" => a, b, c
+		    var currentNode = root;
+		    var searchTarget;
+		    
+		    for(var idx in nodes){
+		        searchTarget = currentNode.getChildren();
+		        for( var jdx in  searchTarget){
+		            if ( searchTarget[jdx].data.title === nodes[idx] ) {
+		                currentNode = searchTarget[jdx];
+		                currentNode.expand();
+		                break;
+		            }
+		        }
+		    }
+		}
+		
+		// Traverse the path of selected tree item
+		function getTreePath(node){
+		    var path = "";
+		    if( node.getParent() && node.getParent().data.title !== null ){
+		        path = getTreePath(node.getParent()) + "/" + node.data.title;
+		    } else {
+		        path = node.data.title;
+		    }
+		    return path;
+		}
+		
+		// initial path loading
+		var rootPath = "";
+		var treeSelectorId = "#folderList";
+
+		/*
+		$(function(){
+		    var path = getHash().replace(/^#/, "");
+		    var branch = encodeURIComponent($("#selected-branch").text());
+		    rootPath = "code/" + branch + "/!/";
+		    $.ajax({
+		        url: rootPath,
+		        success: function(result, textStatus){
+		            treeInit(adaptorForDynatree(result.data));
+		            findTreeNode(path.substr(1));  // path.substr(1) "/a/b/c" => "a/b/c"
+		        }
+		    });
+		});
+		*/
+
+		function _updateDynaTree(){
+//			$("#folderList").dynatree("getRoot").removeChildren(true);
+			
+		    var path = getHash().replace(/^#/, "");
+		    var branch = encodeURIComponent($("#selected-branch").text());
+		    rootPath = "code/" + branch + "/!/";
+		    $.ajax({
+		        url: rootPath,
+		        success: function(result, textStatus){
+		            treeInit(adaptorForDynatree(result.data));
+		            findTreeNode(path.substr(1));  // path.substr(1) "/a/b/c" => "a/b/c"
+		        }
+		    });
+		}
+		_updateDynaTree();
+
+		// DynaTree Init function
+		// see: http://wwwendt.de/tech/dynatree/doc/dynatree-doc.html
+		function treeInit(initData){
+			$(treeSelectorId).dynatree({
+		        fx: {  height: "toggle", duration: 200 },
+		        autoFocus: false,
+		        isLazy: true,
+		        onLazyRead: function(node){
+		            $.ajax({
+		                url: rootPath + getTreePath(node),
+		                success: function(result, textStatus) {
+		                    // Called after nodes have been created and the waiting icon was removed.
+		                    // 'this' is the options for this Ajax request
+		                    if(result){
+		                        node.setLazyNodeStatus(DTNodeStatus_Ok);
+		                        node.addChild(adaptorForDynatree(result.data));
+		                    }else{
+		                        // Server returned an error condition: set node status accordingly
+		                        node.setLazyNodeStatus(DTNodeStatus_Error, {
+		                            tooltip: "Loading failed",
+		                            info: result
+		                        });
+		                    }
+		                },
+		                error: function(node, XMLHttpRequest, textStatus, errorThrown) {
+		                    // Called on error, after error icon was created.
+		                    console.log(node);
+		                },
+		                cache: false // Append random '_' argument to url to prevent caching.
+		            });
+		        },
+		        onActivate: function(node) {
+		            // A DynaTreeNode object is passed to the activation handler
+		            // Note: we also get this event, if persistence is on, and the page is reloaded.
+		            window.location = "#/" + getTreePath(node);
+		        },
+		        title: "/",
+		        children: initData,
+		        debugLevel: 0
+		    });
+		}
+	};
+})("hive.code.Browser1");(No newline at end of file)
Add a comment
List