瀏覽代碼

HUE-1414 [hbase] Searchbar Filter Autocomplete

Kevin Wang 12 年之前
父節點
當前提交
a74da344ba
共有 3 個文件被更改,包括 79 次插入19 次删除
  1. 4 0
      apps/hbase/src/hbase/templates/app.mako
  2. 24 0
      apps/hbase/static/css/hbase.css
  3. 51 19
      apps/hbase/static/js/controls.js

+ 4 - 0
apps/hbase/src/hbase/templates/app.mako

@@ -205,6 +205,10 @@ ${ commonheader(None, "hbase", user) | n,unicode }
             <!-- ko foreach: search.activeHints() -->
             <li data-bind="event: { mousedown: function(){app.search.cur_input(app.search.cur_input() + $data.shortcut);} }, css: {active: self.activeHint}"><a><span data-bind="text: $data.hint"></span> <code class="pull-right" data-bind="text: $data.shortcut"></code></a></li>
             <!-- /ko -->
+            <li class="search-suggestion-header" data-bind="visible: search.activeSuggestions().length > 0"><a>${_('Autocomplete Suggestions:')}</a></li>
+            <!-- ko foreach: search.activeSuggestions() -->
+            <li class="search-suggestion" data-bind="event: { mousedown: app.search.replaceFocusNode.bind(null, $data) }"><a><span data-bind="text: $data"></span></a></li>
+            <!-- /ko -->
           </ul>
           <button class="btn btn-primary add-on" data-bind="enabled: !search.submitted(), click: search.evaluate.bind(null)"><i class="icon-search"></i></button>
           <span id="column-family-selectors">

+ 24 - 0
apps/hbase/static/css/hbase.css

@@ -578,3 +578,27 @@ textarea {
 	color: #777;
 	text-decoration: none;
 }
+
+#search-typeahead .search-suggestion a
+{
+	color: #eee;
+	background: #333;
+	border-color: #777;
+}
+
+#search-typeahead .search-suggestion-header a
+{
+	padding: 5px;
+	color: #4DB8EA;
+	font-weight: bold;
+	background: #292b2d; /* Old browsers */
+	background: -moz-linear-gradient(top,  #292b2d 0%, #000000 100%); /* FF3.6+ */
+	background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#292b2d), color-stop(100%,#000000)); /* Chrome,Safari4+ */
+	background: -webkit-linear-gradient(top,  #292b2d 0%,#000000 100%); /* Chrome10+,Safari5.1+ */
+	background: -o-linear-gradient(top,  #292b2d 0%,#000000 100%); /* Opera 11.10+ */
+	background: -ms-linear-gradient(top,  #292b2d 0%,#000000 100%); /* IE10+ */
+	background: linear-gradient(to bottom,  #292b2d 0%,#000000 100%); /* W3C */
+	filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#292b2d', endColorstr='#000000',GradientType=0 ); /* IE6-9 */
+	border-color: #333;
+	box-shadow: 0px 3px 5px rgba(0,0,0,.3);
+}

+ 51 - 19
apps/hbase/static/js/controls.js

@@ -24,10 +24,10 @@ var searchRenderers = {
         'prefix': { select: /[^\*]+\*/g, tag: /\*/g},
         'filter': {
           select: /\{[^\{\}]+\}/,
-          tag:/.+/g,
+          tag:/[^\{\}]+/g,
           nested: {
             'linker': {
-              select: /AND|OR|SKIP|WHILE/g,
+              select: /\ (AND|OR|SKIP|WHILE)\ /g,
               tag: /.+/g
             }/*,
             'compare_op': {
@@ -562,6 +562,7 @@ var tagsearch = function() {
   self.mode = ko.observable('idle');
   self.cur_input = ko.observable('');
   self.submitted = ko.observable(false);
+  self.filters = ["KeyOnlyFilter ()", "FirstKeyOnlyFilter ()", "PrefixFilter (‘row_prefix’)", "ColumnPrefixFilter(‘column_prefix’)", "MultipleColumnPrefixFilter(‘column_prefix’, ‘column_prefix’, …, ‘column_prefix’)", "ColumnCountGetFilter (‘limit’)", "PageFilter (‘page_size’)", "ColumnPaginationFilter(‘limit’, ‘offest')", "InclusiveStopFilter(‘stop_row_key’)", "TimeStampsFilter (timestamp, timestamp, ... ,timestamp)", "RowFilter (compareOp, ‘row_comparator’)", "QualifierFilter (compareOp, ‘qualifier_comparator’)", "QualifierFilter (compareOp,‘qualifier_comparator’)", "ValueFilter (compareOp,‘value_comparator’)", "DependentColumnFilter (‘family’, ‘qualifier’, boolean, compare operator, ‘value comparator’)", "DependentColumnFilter (‘family’, ‘qualifier’, boolean)", "DependentColumnFilter (‘family’, ‘qualifier’)", "SingleColumnValueFilter(‘family’, ‘qualifier’, compare operator, ‘comparator’, filterIfColumnMissing_boolean, latest_version_boolean)", "SingleColumnValueFilter(‘family’, ‘qualifier, compare operator, ‘comparator’)", "SingleColumnValueExcludeFilter('family', 'qualifier', compare operator, 'comparator', latest_version_boolean, filterIfColumnMissing_boolean)", "SingleColumnValueExcludeFilter('family', 'qualifier', compare operator, 'comparator')", "ColumnRangeFilter (‘minColumn’, minColumnInclusive_bool, ‘maxColumn’, maxColumnInclusive_bool)"];
   self.hints = ko.observableArray([ {
       hint: 'End Query',
       shortcut: ',',
@@ -640,6 +641,7 @@ var tagsearch = function() {
 
   self.modeQueue = ['idle'];
   self.focused = ko.observable(false);
+  self.activeSuggestions = ko.observableArray();
 
   self.insertTag = function(tag) {
     var mode = tag.indexOf('+') != -1 ? 'scan' : 'rowkey';
@@ -674,7 +676,7 @@ var tagsearch = function() {
       self.mode('idle');
       return;
     }
-    var tokens = "[]+,*{}";
+    var tokens = "[]+*{}";
     var m = 'rowkey';
     for(var i=selection.length - 1; i>=0; i--) {
       if(tokens.indexOf(selection[i]) != -1) {
@@ -698,17 +700,27 @@ var tagsearch = function() {
   self.selectionEnd = ko.observable(0);
 
   self.hintText = ko.computed(function() {
-    var value = self.cur_input();
-    var selection = value.slice(0, self.selectionEnd());
-    var index = selection.lastIndexOf(',') + 1;
-    var endindex = value.slice(index).indexOf(',');
-    endindex = endindex == -1 ? value.length : endindex;
-    var pre = value.substring(index, index + endindex);
-    var s = self.selectionStart() - index, e = self.selectionEnd() - index;
-    if(s == e)
-      e += 1;
-    s = s < 0 ? 0 : s;
-    e = e > pre.length ? pre.length : e;
+    var pre, s, e;
+    try {
+      var r = window.getSelection().getRangeAt(0);
+      pre = r.startContainer.nodeValue;
+      s = r.startOffset;
+      e = r.endOffset;
+      return pre.slice(0, s) + "<span class='selection'>" + pre.slice(s, e) + "</span>" + pre.slice(e);
+    } catch (e) {
+      var value = self.cur_input();
+      var selection = value.slice(0, self.selectionEnd());
+      var index = selection.lastIndexOf(',') + 1;
+      var endindex = value.slice(index).indexOf(',');
+      endindex = endindex == -1 ? value.length : endindex;
+      pre = value.substring(index, index + endindex);
+      s = self.selectionStart() - index;
+      e = self.selectionEnd() - index;
+      if(s == e)
+        e += 1;
+      s = s < 0 ? 0 : s;
+      e = e > pre.length ? pre.length : e;
+    }
     return pre.slice(0, s) + "<span class='selection'>" + pre.slice(s, e) + "</span>" + pre.slice(e);
   });
 
@@ -723,12 +735,32 @@ var tagsearch = function() {
 
   self.updateMenu = function() {
     try{
-    	var pos = getEditablePosition(document.getElementById('search-tags'));
-	  	self.selectionStart(pos);
-	  	self.selectionEnd(pos);
+      var pos = getEditablePosition(document.getElementById('search-tags'));
+      self.selectionStart(pos);
+      self.selectionEnd(pos);
     } catch (err) {}
-	self.updateMode(self.cur_input());
-  };
+	  self.updateMode(self.cur_input());
+    self.updateSuggestions();
+  };
+
+  self.replaceFocusNode = function(text) {
+    window.getSelection().getRangeAt(0).startContainer.nodeValue = text;
+  };
+
+  self.updateSuggestions = function() {
+    var val = window.getSelection().getRangeAt(0).startContainer.nodeValue;
+    switch(self.mode()) {
+      case 'filter':
+        var focus = val.replace(/\{|\}|\s|&[^;]+?;/g,"").split(/(AND|OR|SKIP|WHILE)/).slice(-1)[0];
+        self.activeSuggestions(self.filters.filter(function(a) {
+          return a.replace(" ","").indexOf(focus) != -1;
+        }));
+        return;
+      default:
+        self.activeSuggestions([]);
+        return;
+    }
+  }
 
   self.evaluate = function() {
     table_search(self.cur_input());