blob: aeb427342e110254f94ee0d105d28ea339ff7903 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
var htrace = htrace || {};
htrace.SearchView = Backbone.View.extend({
initialize : function() {
this.predicateViews = [];
this.highestPredicateIndex = 0;
this.searchInProgress = false;
this.searchResults = new htrace.SearchResults();
this.resultsView = new htrace.SearchResultsView({
searchResults: this.searchResults,
el: "#resultsView"
});
},
events: {
"click #searchButton": "searchHandler",
"click #clearButton": "clearHandler",
"click .add-field": "dropdownHandler",
"blur #begin": "blurBeginHandler",
"blur #end": "blurEndHandler",
"click #zoomButton": "zoomHandler"
},
searchHandler: function(e){
e.preventDefault();
this.doSearch(e.ctrlKey);
},
clearHandler: function(e){
e.preventDefault();
this.resultsView.clearHandler(true);
},
doSearch: function(showDebug){
if (this.searchInProgress) {
console.log("Can't start a new search while another one is in " +
"progress.");
return false;
}
// Check if there are no search criteria.
if (this.predicateViews.length == 0) {
htrace.showModalWarning("No Search Criteria Specified",
"You have not specified any search criteria. " +
"Use the 'Add Predicate' button to specify what to search for.");
return false;
}
// Build the predicate array.
predicates = []
var predicateViewsLen = this.predicateViews.length;
for (var i = 0; i < predicateViewsLen; i++) {
var predicateView = this.predicateViews[i];
try {
predicates.push(predicateView.getPredicate());
} catch(err) {
htrace.showModalWarning("Search Field Validation Error",
"Invalid search string for the '" + predicateView.ptype.name +
"' field.<p/>" + err);
return false;
}
}
var queryJson = {
pred: predicates,
lim: 20
};
// If there are existing search results, we want results which "come after"
// those. So pass the last span we saw as a continuation token.
if (this.searchResults.size() > 0) {
queryJson.prev =
this.searchResults.at(this.searchResults.size() - 1).unparse();
}
var searchView = this;
var queryResults = new htrace.QueryResults({queryJson: queryJson});
console.log("Starting span query " + queryResults.url());
this.searchInProgress = true;
queryResults.fetch({
success: function(model, response, options){
var firstResults = (searchView.searchResults.size() === 0);
console.log("Success on span query " + queryResults.url() + ": got " +
queryResults.size() + " result(s). firstResults=" + firstResults);
searchView.searchResults.add(queryResults.models);
if (firstResults) {
// After the initial search, zoom to fit everything.
// On subsequent searches, we leave the viewport alone.
searchView.resultsView.zoomHandler();
}
searchView.searchInProgress = false;
if (showDebug) {
htrace.showModalWarning("Search Debug",
"This is the search debug box, accessible by holding down the " +
"control key while clicking the search button.<p/>" +
"<h3>Query JSON</h3><pre>" + queryResults.prettyQueryString() +
"</pre><p/><h3>Response JSON</h3><pre>" +
JSON.stringify(queryResults, null, 2) + "</pre><p/>");
} else if (queryResults.size() == 0) {
if (firstResults) {
htrace.showModalWarning("No Results Found",
"No results were found for your query.<p/>");
} else {
htrace.showModalWarning("No Additional Results Found",
"No additional results were found for your query.<p/>");
}
}
searchView.resultsView.render();
},
error: function(model, response, options){
searchView.searchResults.reset();
var err = "Error " + JSON.stringify(response, null, 2) +
" on span query " + queryResults.url();
console.log(err);
alert(err);
searchView.searchInProgress = false;
}
});
return false;
},
dropdownHandler: function(e){
e.preventDefault();
var text = $(e.target).text();
var ptype = htrace.parsePType(text);
if (!ptype) {
alert("Unable to parse predicate type '" + text + "'");
return false;
}
var index = this.highestPredicateIndex;
this.highestPredicateIndex++;
var el = "pred" + index;
$("#predicates").append('<div id="' + el + '"/></div>');
predicateView = new htrace.PredicateView({
el: "#" + el,
index: index,
ptype: ptype,
searchView: this
});
this.predicateViews.push(predicateView);
predicateView.render();
return true;
},
blurBeginHandler: function(e) {
return this.resultsView.handleBeginOrEndChange(e, "begin");
},
blurEndHandler: function(e) {
return this.resultsView.handleBeginOrEndChange(e, "end");
},
zoomHandler: function(e) {
e.preventDefault();
this.resultsView.zoomHandler();
},
removePredicateView: function(predicateView) {
this.predicateViews = _.without(this.predicateViews, predicateView);
},
render: function() {
this.$el.html(_.template($("#search-view-template").html())
({ model : this.model }))
this.resultsView.render();
console.log("SearchView#render");
return this;
},
close: function() {
console.log("SearchView#close")
while (this.predicateViews.length > 0) {
this.predicateViews[0].remove();
}
this.resultsView.remove();
this.resultsView = null;
this.undelegateEvents();
}
});