Commit e2a779a7 authored by Piotr Gawron's avatar Piotr Gawron
Browse files

autocomple list contain also values from inside queries, match string are highlighted

parent 4734ceaa
......@@ -261,6 +261,7 @@
}
.tt-suggestion {
font-weight: normal;
padding: 3px 20px;
line-height: 24px;
}
......@@ -276,6 +277,11 @@
background-color: #0097cf;
}
.tt-suggestion strong {
font-weight: normal;
color: red;
}
.dropdown-submenu {
position: relative;
}
......
......@@ -26,80 +26,82 @@ function AbstractPanel(params) {
AbstractPanel.prototype = Object.create(Panel.prototype);
AbstractPanel.prototype.constructor = AbstractPanel;
AbstractPanel.prototype._createEventHandlers = function() {
AbstractPanel.prototype._createEventHandlers = function () {
var self = this;
var searchButton = self.getControlElement(PanelControlElementType.SEARCH_BUTTON);
var searchInput = self.getControlElement(PanelControlElementType.SEARCH_INPUT);
var searchByQuery = function() {
var searchByQuery = function () {
return self.searchByQuery();
};
searchButton.onclick = searchByQuery;
searchInput.onkeypress = function(event) {
searchInput.onkeypress = function (event) {
if (event.keyCode === 13) {
return searchByQuery().then(null, GuiConnector.alert);
}
};
$(searchInput).typeahead({
minLength : 1,
minLength: 1,
hint: true,
highlight: true
}, {
source : function(query, callback) {
callback(self.getAutocomplete(query));
source: function (query, callback) {
callback(self.getAutocomplete(query.toLowerCase()));
}
});
$(searchInput).on('typeahead:select', function() {
$(searchInput).on('typeahead:select', function () {
searchByQuery();
});
self.getOverlayDb().addListener("onSearch", function() {
self.getOverlayDb().addListener("onSearch", function () {
return self.refreshSearchResults();
});
self.getOverlayDb().addListener("onClear", function() {
self.getOverlayDb().addListener("onClear", function () {
searchInput.value = "";
});
};
AbstractPanel.prototype._initializeGui = function(placeholder) {
AbstractPanel.prototype._initializeGui = function (placeholder) {
var searchQueryDiv = Functions.createElement({
type : "div",
name : "searchQuery",
className : "searchPanel"
type: "div",
name: "searchQuery",
className: "searchPanel"
});
this.getElement().appendChild(searchQueryDiv);
this.setControlElement(PanelControlElementType.SEARCH_DIV, searchQueryDiv);
var searchLabel = Functions.createElement({
type : "div",
name : "searchLabel",
content : "SEARCH:"
type: "div",
name: "searchLabel",
content: "SEARCH:"
});
searchQueryDiv.appendChild(searchLabel);
this.setControlElement(PanelControlElementType.SEARCH_LABEL, searchLabel);
var searchInputDiv = Functions.createElement({
type : "table",
type: "table",
});
searchQueryDiv.appendChild(searchInputDiv);
var searchInputRow = Functions.createElement({
type : "tr",
type: "tr",
});
searchInputDiv.appendChild(searchInputRow);
var searchInputCell = Functions.createElement({
type : "td",
type: "td",
});
searchInputRow.appendChild(searchInputCell);
var searchInput = Functions.createElement({
type : "input",
name : "searchInput",
className : "input-field typeahead"
type: "input",
name: "searchInput",
className: "input-field typeahead"
});
if (placeholder !== undefined) {
searchInput.placeholder = placeholder;
......@@ -108,56 +110,56 @@ AbstractPanel.prototype._initializeGui = function(placeholder) {
this.setControlElement(PanelControlElementType.SEARCH_INPUT, searchInput);
var searchButtonCell = Functions.createElement({
type : "td",
type: "td",
});
searchInputRow.appendChild(searchButtonCell);
var searchButton = Functions.createElement({
type : "a",
content : '<img src="resources/images/icons/search.png"/>'
type: "a",
content: '<img src="resources/images/icons/search.png"/>'
});
searchButton.href = "#";
searchButtonCell.appendChild(searchButton);
this.setControlElement(PanelControlElementType.SEARCH_BUTTON, searchButton);
var searchResultsDiv = Functions.createElement({
type : "div",
name : "searchResults",
className : "tabbable boxed parentTabs"
type: "div",
name: "searchResults",
className: "tabbable boxed parentTabs"
});
this.getElement().appendChild(searchResultsDiv);
this.setControlElement(PanelControlElementType.SEARCH_RESULTS_DIV, searchResultsDiv);
var searchResultsNavTabDiv = Functions.createElement({
type : "ul",
className : "nav nav-tabs",
content : '<li class="active"><a href="#set1"/></li>'
type: "ul",
className: "nav nav-tabs",
content: '<li class="active"><a href="#set1"/></li>'
});
searchResultsDiv.appendChild(searchResultsNavTabDiv);
this.setControlElement(PanelControlElementType.SEARCH_RESULTS_NAV_TAB, searchResultsNavTabDiv);
var searchResultsContentTabDiv = Functions.createElement({
type : "div",
className : "tab-content",
content : '<div class="tab-pane fade active in" name="set1" id="set1"/>'
type: "div",
className: "tab-content",
content: '<div class="tab-pane fade active in" name="set1" id="set1"/>'
});
searchResultsDiv.appendChild(searchResultsContentTabDiv);
this.setControlElement(PanelControlElementType.SEARCH_RESULTS_CONTENT_TAB, searchResultsContentTabDiv);
};
AbstractPanel.prototype.setOverlayDb = function(overlayDb) {
AbstractPanel.prototype.setOverlayDb = function (overlayDb) {
if (overlayDb === undefined) {
throw new Error("Undefined overlayDb for panel: " + this.getPanelName());
}
this._overlayDb = overlayDb;
};
AbstractPanel.prototype.getOverlayDb = function() {
AbstractPanel.prototype.getOverlayDb = function () {
return this._overlayDb;
};
AbstractPanel.prototype.clearResults = function() {
AbstractPanel.prototype.clearResults = function () {
var navElement = this.getControlElement(PanelControlElementType.SEARCH_RESULTS_NAV_TAB);
while (navElement.firstChild) {
navElement.removeChild(navElement.firstChild);
......@@ -169,7 +171,7 @@ AbstractPanel.prototype.clearResults = function() {
}
};
AbstractPanel.prototype.refreshSearchResults = function() {
AbstractPanel.prototype.refreshSearchResults = function () {
var self = this;
self.clearResults();
var searchDb = self.getOverlayDb();
......@@ -179,7 +181,7 @@ AbstractPanel.prototype.refreshSearchResults = function() {
for (var i = 0; i < queries.length; i++) {
promises.push(searchDb.getElementsByQuery(queries[i]));
}
return Promise.all(promises).then(function(results) {
return Promise.all(promises).then(function (results) {
for (var i = 0; i < queries.length; i++) {
self.addResultTab(queries[i], results[i]);
}
......@@ -188,15 +190,15 @@ AbstractPanel.prototype.refreshSearchResults = function() {
};
AbstractPanel.prototype.getAutocomplete = function() {
AbstractPanel.prototype.getAutocomplete = function () {
logger.warn("Get autocomplete not implemented");
};
AbstractPanel.prototype.searchByQuery = function() {
AbstractPanel.prototype.searchByQuery = function () {
throw new Error("searchByQuery is not implemented");
};
AbstractPanel.prototype.addResultTab = function(query, elements) {
AbstractPanel.prototype.addResultTab = function (query, elements) {
var name = JSON.parse(query).query;
var tabId = this.getPanelName() + "Tab_" + this._tabIdCount;
......@@ -215,9 +217,9 @@ AbstractPanel.prototype.addResultTab = function(query, elements) {
navLi.className = navClass;
var navLink = Functions.createElement({
type : "a",
href : "#" + tabId,
onclick : function() {
type: "a",
href: "#" + tabId,
onclick: function () {
$(this).tab('show');
}
});
......@@ -256,7 +258,7 @@ AbstractPanel.prototype.addResultTab = function(query, elements) {
}
};
AbstractPanel.prototype.createTargetRow = function(target, icon) {
AbstractPanel.prototype.createTargetRow = function (target, icon) {
var self = this;
var guiUtils = self.getGuiUtils();
var result = document.createElement("tr");
......@@ -273,7 +275,7 @@ AbstractPanel.prototype.createTargetRow = function(target, icon) {
var checkbox = document.createElement('input');
checkbox.type = "checkbox";
checkbox.checked = target.isVisible();
checkbox.onclick = function() {
checkbox.onclick = function () {
target.setIsVisible(!target.isVisible());
self.getOverlayDb().callListeners("onTargetVisibilityChange");
};
......@@ -294,27 +296,27 @@ AbstractPanel.prototype.createTargetRow = function(target, icon) {
descColumn.appendChild(guiUtils.createParamLine("Name: ", target.getName()));
descColumn.appendChild(guiUtils.createAnnotations("Elements: ", target.getTargetParticipants(), {
showType : false,
inline : true
showType: false,
inline: true
}));
descColumn.appendChild(guiUtils.createAnnotations("References: ", target.getReferences(), {
showType : false,
showType: false,
}));
if (submaps.length > 0) {
descColumn.appendChild(guiUtils.createLabel("Available in submaps: "));
for (i = 0; i < submaps.length; i++) {
var model = self.getMap().getSubmapById(submaps[i]).getModel();
var onclick = (function() {
var onclick = (function () {
var id = model.getId();
return function() {
return function () {
self.getMap().openSubmap(id);
};
}());
var button = Functions.createElement({
type : "button",
className : "minerva-open-submap-button",
content : model.getName(),
onclick : onclick,
type: "button",
className: "minerva-open-submap-button",
content: model.getName(),
onclick: onclick,
});
descColumn.appendChild(button);
}
......
......@@ -1113,30 +1113,64 @@ CustomMap.prototype.fetchIdentifiedElements = function (elements, complete) {
};
CustomMap.prototype.refreshSearchAutocomplete = function () {
var self = this;
self._searchAutocomplete = [];
return ServerConnector.getSuggestedQueryList().then(function (queries) {
for (var i = 0; i < queries.length; i++) {
var mainString = queries[i];
for (var j = 0; j < mainString.length; j++) {
var substring = mainString.substring(0, j + 1);
if (self._searchAutocomplete[substring] !== undefined) {
continue;
CustomMap.prototype.computeAutocompleteDictionary = function (queries) {
var result = {};
var i, j, k, mainString, substring, list;
//compute dict for prefixes
for (i = 0; i < queries.length; i++) {
mainString = queries[i];
for (j = 0; j < mainString.length; j++) {
substring = mainString.substring(0, j + 1);
if (result[substring] !== undefined) {
continue;
}
list = [];
for (k = 0; k < 5; k++) {
if (k + i >= queries.length) {
break;
} else if (queries[k + i].toLowerCase().startsWith(substring.toLowerCase())) {
list.push(queries[k + i]);
}
}
result[substring] = list;
}
}
var list = [];
for (var k = 0; k < 5; k++) {
if (k + i >= queries.length) {
break;
} else if (queries[k + i].toLowerCase().startsWith(substring.toLowerCase())) {
list.push(queries[k + i]);
//and now we add substring from inside
for (i = 0; i < queries.length; i++) {
mainString = queries[i];
for (var startSubstring = 1; startSubstring < mainString.length; startSubstring++) {
for (var endSubstring = startSubstring + 1; endSubstring <= mainString.length; endSubstring++) {
substring = mainString.substring(startSubstring, endSubstring);
if (!mainString.startsWith(substring)) {
if (result[substring] === undefined) {
result[substring] = [];
}
if (result[substring].length < 5) {
var found = false;
for (k = 0; k < result[substring].length; k++) {
found |= result[substring][k] === mainString;
}
if (!found) {
result[substring].push(mainString);
}
}
}
self._searchAutocomplete[substring] = list;
}
}
}
return result;
};
CustomMap.prototype.refreshSearchAutocomplete = function () {
var self = this;
self._searchAutocomplete = [];
return ServerConnector.getSuggestedQueryList().then(function (queries) {
self._searchAutocomplete = self.computeAutocompleteDictionary(queries);
return self._searchAutocomplete;
});
};
......@@ -1313,7 +1347,7 @@ CustomMap.prototype.createSurfaceForDbOverlay = function (element, dbOverlay) {
}, function () {
return self.callListeners("onBioEntityClick", element);
}]
}).then(function(surface){
}).then(function (surface) {
result = surface;
result.show();
dbOverlay.mapOverlays[element.getType()][element.getId()] = result;
......
......@@ -246,24 +246,59 @@ describe('CustomMap', function () {
});
});
it("getSearchAutocomplete", function () {
var map = helper.createCustomMap();
describe("getSearchAutocomplete", function () {
it("without initialization", function () {
var map = helper.createCustomMap();
var t = map.getSearchAutocomplete("s");
assert.ok(t);
assert.equal(t.length, 0);
});
var t = map.getSearchAutocomplete("s");
assert.ok(t);
assert.equal(t.length, 0);
it("after initialization", function () {
var map = helper.createCustomMap();
return map.refreshSearchAutocomplete("s").then(function () {
var t = map.getSearchAutocomplete("s");
assert.ok(t);
assert.ok(t.length > 0);
});
});
});
it("getSearchAutocomplete 2", function () {
var map = helper.createCustomMap();
describe("computeAutocompleteDictionary", function () {
it("using prefixes", function () {
var queries = ["text 1", "text 2", "text 3", "alphabet"];
var map = helper.createCustomMap();
return map.refreshSearchAutocomplete("s").then(function () {
var t = map.getSearchAutocomplete("s");
assert.ok(t);
assert.ok(t.length > 0);
var dictionary = map.computeAutocompleteDictionary(queries);
assert.ok(dictionary);
assert.equal(dictionary["te"].length, 3);
});
it("using prefixes and inside", function () {
var queries = ["text 1", "text 2", "text 3", "alphabet", "unknown"];
var map = helper.createCustomMap();
var dictionary = map.computeAutocompleteDictionary(queries);
assert.ok(dictionary);
assert.equal(dictionary["t"].length, 4);
assert.equal(dictionary["t"][0], "text 1");
assert.equal(dictionary["t"][3], "alphabet");
});
it("function names as query list", function () {
var queries = ["-pop", "some", "map"];
var map = helper.createCustomMap();
var dictionary = map.computeAutocompleteDictionary(queries);
assert.ok(dictionary);
assert.equal(dictionary["p"].length, 2);
});
});
describe("renderOverlayCollection", function () {
it("for alias", function () {
var map = helper.createCustomMap();
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment