| /* |
| * 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(); |
| } |
| }); |