Added Tree Explorer Search
Change-Id: I3de5ec2ad84526b6308f37f4a6df7396175d183a
diff --git a/client/catalog/css/style.css b/client/catalog/css/style.css
index e9593b3..1a66da4 100644
--- a/client/catalog/css/style.css
+++ b/client/catalog/css/style.css
@@ -124,3 +124,46 @@
.disabled {
cursor: not-allowed;
}
+
+.panel-heading a[data-toggle="collapse"]::after {
+ font-family: "Glyphicons Halflings";
+ content: "\e114";
+ float: right;
+ color: gray;
+}
+
+.panel-heading a[data-toggle="collapse"].collapsed::after {
+ content: "\e080";
+}
+
+.treeExplorer .treeExplorerNode {
+ padding-left: 25px;
+ display: block;
+ cursor: pointer;
+}
+
+.treeExplorer .treeExplorerNode > .nodeChildren {
+ display: none;
+}
+
+.treeExplorer .treeExplorerNode.open > .nodeChildren {
+ display: block;
+}
+
+.treeExplorer .treeExplorerNode::before {
+ font-family: "Glyphicons Halflings";
+ content: "\e080";
+ color: gray;
+}
+
+.treeExplorer .treeExplorerNode.open::before {
+ content: "\e114";
+}
+
+.treeExplorer .treeExplorerNode.file {
+ cursor: default;
+}
+
+.treeExplorer .treeExplorerNode.file::before {
+ content: "\e022"
+}
diff --git a/client/catalog/index.html b/client/catalog/index.html
index 61e4215..bd2e933 100644
--- a/client/catalog/index.html
+++ b/client/catalog/index.html
@@ -24,6 +24,7 @@
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
<script src="../ndn-js/build/ndn.min.js"></script>
<script src="js/autocomplete.js"></script>
+<script src="js/treeExplorer.js"></script>
<script src="js/catalog.js"></script>
</head>
@@ -82,6 +83,13 @@
</div>
</div>
+ <div class="panel panel-info">
+ <div class="panel-heading">Tree Based Search<a data-toggle="collapse" class="collapsed" data-target="#treeSearch" href="#treeSearch"></a></div>
+ <div class="panel-body collapse" id="treeSearch">
+ <div></div>
+ </div>
+ </div>
+
<div id="results" class="panel panel-default hidden">
<div class="panel-body">
<nav class="navbar navbar-inverse col-md-12 resultMenu hidden">
diff --git a/client/catalog/js/catalog.js b/client/catalog/js/catalog.js
index 347366e..3f703cb 100644
--- a/client/catalog/js/catalog.js
+++ b/client/catalog/js/catalog.js
@@ -81,11 +81,23 @@
this.filterSetup();
this.searchInput.autoComplete(function(field, callback){
- scope.autoComplete(field, callback);
+ scope.autoComplete(field, function(list){
+ callback(list.map(function(element){
+ return field + element + "/";
+ }));
+ });
});
this.searchBar.submit(function(e){
e.preventDefault();
+ if (scope.searchInput.val().length === 0){
+ if (!scope.searchBar.hasClass('has-error')){
+ scope.searchBar.addClass('has-error').append('<span class="help-block">Search path is required!</span>');
+ }
+ return;
+ } else {
+ scope.searchBar.removeClass('has-error').find('.help-block').fadeOut(function(){$(this).remove()});
+ }
scope.pathSearch();
});
@@ -120,6 +132,16 @@
});
+ $('#treeSearch div').treeExplorer(function(path, callback){
+ console.log("Tree Explorer request", path);
+ scope.autoComplete(path, function(list){
+ console.log("Autocomplete response", list);
+ callback(list.map(function(element){
+ return (path == "/"?"/":"") + element + "/";
+ }));
+ })
+ });
+
}
Atmos.prototype.clearResults = function(){
@@ -182,15 +204,6 @@
Atmos.prototype.autoComplete = function(field, callback){
- if (this.searchInput.val().length === 0 && !filters.hasOwnProperty()){
- if (!this.searchBar.hasClass('has-error')){
- this.searchBar.addClass('has-error').append('<span class="help-block">A filter or search value is required!</span>');
- }
- return;
- } else {
- this.searchBar.removeClass('has-error').find('.help-block').fadeOut(function(){$(this).remove()});
- }
-
var scope = this;
this.query(this.catalog, {"?": field},
@@ -206,10 +219,9 @@
function(interest, data){
if (data.getContent().length !== 0){
- var options = JSON.parse(data.getContent().toString().replace(/[\n\0]/g, "")).next.map(function(element){
- return field + element + "/";
- });
- callback(options);
+ callback(JSON.parse(data.getContent().toString().replace(/[\n\0]/g, "")).next);
+ } else {
+ callback([]);
}
}, function(interest){
diff --git a/client/catalog/js/treeExplorer.js b/client/catalog/js/treeExplorer.js
new file mode 100644
index 0000000..fc6a7a3
--- /dev/null
+++ b/client/catalog/js/treeExplorer.js
@@ -0,0 +1,73 @@
+
+(function(){
+ "use strict";
+ jQuery.fn.extend({
+ treeExplorer: function(getChildren){
+
+ var cache = {}; //Cache previously requested paths.
+
+ var tree = $('<div class="treeExplorer"></div>');
+ this.append(tree);
+
+ var lookup = function(path, callback){
+ if (cache[path]){
+ callback(path, cache[path]);
+ } else {
+ getChildren(path, function(children){
+ cache[path] = children;
+ callback(path, children);
+ });
+ }
+ }
+
+ var append = function(path, children, node){
+ var c = $('<div class="nodeChildren"></div>');
+ node.append(c);
+ children.forEach(function(current){
+ var el = $('<div class="treeExplorerNode"></div>');
+ if (current.match(/\/$/)){
+ el.attr('id', path + current);
+ el.append(['<a href="#' , path , current , '">' , current , '</a>'].join(""));
+ } else {
+ el.addClass('file');
+ el.text(current);
+ }
+ c.append(el);
+ });
+ }
+
+ tree.on('click', '.treeExplorerNode > a', function(){
+ var node = $(this).parent();
+
+ if (node.hasClass('open')){ //Are we open already?
+ node.removeClass('open');
+ return;
+ } else { //We need to open
+ if (node.find('.treeExplorerNode').length > 0){ //We already have children
+ node.addClass('open');
+ } else { //We need to get the children.
+ var path = node.attr('id');
+ lookup(path, function(path, children){
+ if (children.length === 0){
+ node.addClass('file');
+ var name = node.find('a').text().replace(/\/$/, "");
+ node.empty().text(name);
+ } else {
+ append(path, children, node);
+ node.addClass('open');
+ }
+ });
+ }
+ }
+
+ });
+
+ getChildren("/", function(children){
+ append("", children, tree);
+ });
+
+ return this;
+
+ }
+ })
+})();