PageRenderTime 41ms CodeModel.GetById 14ms RepoModel.GetById 1ms app.codeStats 0ms

/static/js/controllers/searchresultcontroller.js

https://bitbucket.org/gordonbrander/accordion-drawer-prototypes
JavaScript | 185 lines | 116 code | 32 blank | 37 comment | 7 complexity | 7026162c181c714975455cb39de61fc9 MD5 | raw file
Possible License(s): Apache-2.0
  1. define([
  2. 'config',
  3. 'config/searchProviders',
  4. 'underscore',
  5. 'backbone',
  6. 'lib/template',
  7. 'lib/routecontroller',
  8. 'models/searchcollections',
  9. 'views/postlistview',
  10. 'views/widgetview',
  11. 'views/searchviews',
  12. 'logger'
  13. ], function(
  14. config,
  15. searchProviders,
  16. util,
  17. Backbone,
  18. template,
  19. RouteController,
  20. searchCollections,
  21. PostListView,
  22. WidgetView,
  23. searchViews,
  24. logger
  25. ) {
  26. // We need to pass an empty array into empty collections that need options
  27. // (null gets interpreted as a value and wrapped). It's a bit fussy, but it
  28. // should be faster to share a single object than create one.
  29. var emptyArray = [];
  30. var SearchResultsController = RouteController.extend({
  31. initialize: function (options) {
  32. // Initialize collections object for storing search collections.
  33. var collections = this.collections = {};
  34. // > Depending on how many providers we end up with, we may want to
  35. // > figure out a way to lazily create collections based on what we
  36. // > actually need. Prototypal objects are fast, though, so it might
  37. // > not actually matter -GB.
  38. collections.bings = new searchCollections.Bing(emptyArray, {
  39. urlTokens: {
  40. base: config.searchRoot,
  41. path: 'bing'
  42. },
  43. urlQuery: {
  44. // `q: query.terms,` should be manually configured in the `enter`
  45. // method using `terms` method.
  46. format: 'json'
  47. }
  48. });
  49. collections.tweets = new searchCollections.Tweets(emptyArray, {
  50. urlTokens: {
  51. base: config.searchRoot,
  52. path: 'twitter'
  53. },
  54. urlQuery: {
  55. // `q: query.terms,` should be manually configured in the `enter`
  56. // method using `terms` method.
  57. format: 'json'
  58. }
  59. });
  60. this.mainView = new searchViews.SearchTabsView();
  61. var bingListView = this.bings(collections.bings);
  62. var tweetListView = this.tweets(collections.tweets);
  63. this.mainView.widgets({
  64. '#bing-results': bingListView,
  65. '#twitter-results': tweetListView
  66. });
  67. this.mainView.bind('activate', function (view) {
  68. var activeView = view.widget(view.active);
  69. var collection = activeView.collection;
  70. if (collection.state() === 'invalid') {
  71. activeView.render();
  72. collection.fetchDebounced();
  73. }
  74. });
  75. this.mainView.activateTab('#bing-results');
  76. },
  77. enter: function (query, options) {
  78. util.extend(this, options || {});
  79. // Set this view as active in the app.
  80. this.appView.widget(
  81. '#main',
  82. this.mainView
  83. );
  84. },
  85. update: function (query, options) {
  86. // Update instance from options.
  87. //
  88. // TODO: I'm not wild about the way this works -- it's too brittle -GB
  89. util.extend(this, options || {});
  90. var terms = this.parseQuery(query).terms;
  91. var collections = this.collections;
  92. // Update terms on all collections.
  93. for(var key in collections) collections[key].terms(terms);
  94. // Fetch active search collection.
  95. this.mainView.widget(this.mainView.active).collection.fetchDebounced();
  96. },
  97. exit: function () {
  98. // Empty collections on exit.
  99. var collections = this.collections;
  100. for (var key in collections) collections[key].reset();
  101. // These memoized collections are available as properties on the
  102. // bings collection.
  103. this.collections.bings.images().reset();
  104. this.collections.bings.suggestions().reset();
  105. },
  106. // Factory function for creating tweet result view with configured
  107. // click handlers. This is all a little bit obtuse, and could probably
  108. // be cleaner, but I want to avoid binding handlers in the view constructor.
  109. tweets: function (collection) {
  110. var searchTweetsView = new searchViews.SearchTweetsView({
  111. collection: collection
  112. });
  113. searchTweetsView.bind('visit', function (placeView, siteModel, e) {
  114. // TODO
  115. }, this);
  116. return searchTweetsView;
  117. },
  118. // Factory function for creating bing result view with configured
  119. // click handlers. This is all a little bit obtuse, and could probably
  120. // be cleaner, but I want to avoid binding handlers in the view constructor.
  121. bings: function (collection) {
  122. var searchBingView = new searchViews.SearchBingView({
  123. collection: collection
  124. });
  125. // Define a handler for `visit` events on the `searchBingView`.
  126. searchBingView.bind('visit', function (placeView, siteModel, e) {
  127. // do nothing, allow the link click to proceed
  128. }, this);
  129. // Define a handler for `suggest` events on the `searchBingView`.
  130. searchBingView.bind('suggest', function (view, model, e) {
  131. // TODO
  132. }, this);
  133. return searchBingView;
  134. },
  135. parseQuery: function (query) {
  136. var // parse out the query - it can be something like twitter/term1/term2
  137. // or just 'term'
  138. terms = query.split('/'),
  139. // a master list of search providers we support, with name: prefix.
  140. // define in config maybe?
  141. providers = searchProviders;
  142. var parsed = {};
  143. // We consider the first term to be a provider if it matches one of the
  144. // providers in our list.
  145. if(terms.length > 1 && providers[terms[0]]) {
  146. parsed.provider = terms.shift();
  147. }
  148. parsed.terms = terms.join(' ');
  149. return parsed;
  150. }
  151. });
  152. return new SearchResultsController();
  153. });