/static/js/controllers/searchresultcontroller.js
JavaScript | 185 lines | 116 code | 32 blank | 37 comment | 7 complexity | 7026162c181c714975455cb39de61fc9 MD5 | raw file
Possible License(s): Apache-2.0
- define([
- 'config',
- 'config/searchProviders',
- 'underscore',
- 'backbone',
- 'lib/template',
- 'lib/routecontroller',
- 'models/searchcollections',
- 'views/postlistview',
- 'views/widgetview',
- 'views/searchviews',
- 'logger'
- ], function(
- config,
- searchProviders,
- util,
- Backbone,
- template,
- RouteController,
- searchCollections,
- PostListView,
- WidgetView,
- searchViews,
- logger
- ) {
- // We need to pass an empty array into empty collections that need options
- // (null gets interpreted as a value and wrapped). It's a bit fussy, but it
- // should be faster to share a single object than create one.
- var emptyArray = [];
- var SearchResultsController = RouteController.extend({
- initialize: function (options) {
- // Initialize collections object for storing search collections.
- var collections = this.collections = {};
- // > Depending on how many providers we end up with, we may want to
- // > figure out a way to lazily create collections based on what we
- // > actually need. Prototypal objects are fast, though, so it might
- // > not actually matter -GB.
- collections.bings = new searchCollections.Bing(emptyArray, {
- urlTokens: {
- base: config.searchRoot,
- path: 'bing'
- },
- urlQuery: {
- // `q: query.terms,` should be manually configured in the `enter`
- // method using `terms` method.
- format: 'json'
- }
- });
- collections.tweets = new searchCollections.Tweets(emptyArray, {
- urlTokens: {
- base: config.searchRoot,
- path: 'twitter'
- },
- urlQuery: {
- // `q: query.terms,` should be manually configured in the `enter`
- // method using `terms` method.
- format: 'json'
- }
- });
- this.mainView = new searchViews.SearchTabsView();
- var bingListView = this.bings(collections.bings);
- var tweetListView = this.tweets(collections.tweets);
- this.mainView.widgets({
- '#bing-results': bingListView,
- '#twitter-results': tweetListView
- });
- this.mainView.bind('activate', function (view) {
- var activeView = view.widget(view.active);
- var collection = activeView.collection;
- if (collection.state() === 'invalid') {
- activeView.render();
- collection.fetchDebounced();
- }
- });
- this.mainView.activateTab('#bing-results');
- },
- enter: function (query, options) {
- util.extend(this, options || {});
- // Set this view as active in the app.
- this.appView.widget(
- '#main',
- this.mainView
- );
- },
- update: function (query, options) {
- // Update instance from options.
- //
- // TODO: I'm not wild about the way this works -- it's too brittle -GB
- util.extend(this, options || {});
- var terms = this.parseQuery(query).terms;
- var collections = this.collections;
- // Update terms on all collections.
- for(var key in collections) collections[key].terms(terms);
- // Fetch active search collection.
- this.mainView.widget(this.mainView.active).collection.fetchDebounced();
- },
- exit: function () {
- // Empty collections on exit.
- var collections = this.collections;
- for (var key in collections) collections[key].reset();
- // These memoized collections are available as properties on the
- // bings collection.
- this.collections.bings.images().reset();
- this.collections.bings.suggestions().reset();
- },
- // Factory function for creating tweet result view with configured
- // click handlers. This is all a little bit obtuse, and could probably
- // be cleaner, but I want to avoid binding handlers in the view constructor.
- tweets: function (collection) {
- var searchTweetsView = new searchViews.SearchTweetsView({
- collection: collection
- });
- searchTweetsView.bind('visit', function (placeView, siteModel, e) {
- // TODO
- }, this);
- return searchTweetsView;
- },
- // Factory function for creating bing result view with configured
- // click handlers. This is all a little bit obtuse, and could probably
- // be cleaner, but I want to avoid binding handlers in the view constructor.
- bings: function (collection) {
- var searchBingView = new searchViews.SearchBingView({
- collection: collection
- });
- // Define a handler for `visit` events on the `searchBingView`.
- searchBingView.bind('visit', function (placeView, siteModel, e) {
- // do nothing, allow the link click to proceed
- }, this);
- // Define a handler for `suggest` events on the `searchBingView`.
- searchBingView.bind('suggest', function (view, model, e) {
- // TODO
- }, this);
- return searchBingView;
- },
- parseQuery: function (query) {
- var // parse out the query - it can be something like twitter/term1/term2
- // or just 'term'
- terms = query.split('/'),
- // a master list of search providers we support, with name: prefix.
- // define in config maybe?
- providers = searchProviders;
- var parsed = {};
- // We consider the first term to be a provider if it matches one of the
- // providers in our list.
- if(terms.length > 1 && providers[terms[0]]) {
- parsed.provider = terms.shift();
- }
- parsed.terms = terms.join(' ');
- return parsed;
- }
- });
- return new SearchResultsController();
- });