PageRenderTime 44ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/pancake-web/pancake/web/static/js/views/searchviews.js

https://bitbucket.org/mozillapancake/pancake
JavaScript | 179 lines | 123 code | 40 blank | 16 comment | 4 complexity | 96ed19909ec05e22c23c7cad8331f0ee MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception, LGPL-2.1, MIT, Apache-2.0
  1. /* This Source Code Form is subject to the terms of the Mozilla Public
  2. * License, v. 2.0. If a copy of the MPL was not distributed with this
  3. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  4. define([
  5. 'underscore',
  6. 'backbone',
  7. '$',
  8. 'views/widgetview',
  9. 'views/postlistview',
  10. 'views/thumbnaillistview',
  11. 'views/suggestionlistview',
  12. 'views/urllistview',
  13. 'lib/template'
  14. ], function (
  15. util,
  16. Backbone,
  17. $,
  18. WidgetView,
  19. PostListView,
  20. ThumbnailListView,
  21. SuggestionListView,
  22. UrlListView,
  23. template
  24. ) {
  25. var slice = Array.prototype.slice;
  26. var __PostListView = PostListView.prototype;
  27. // Create a specialized post list view that uses a custom HTML template
  28. // to render.
  29. var SearchView = __PostListView.view.extend({
  30. className: 'post post--result',
  31. template: template('<h1 class="title"><a class="link" href="{place_url}">{{place_title}}</a></h1><div class="content">{{summary}}</div><div class="meta"><a class="link" href="{place_url}">{place_url}</a></div>')
  32. });
  33. var SearchStatusView = __PostListView.statusView.extend({
  34. className: 'post',
  35. template: template('<a class="link" href="{place_url}"><div class="content content--p2">{{summary}}</div><address class="byline"><div class="media media--avatar"><img src="{avatar}"></div><span class="name"><span class="fn">{{author}}</span> {extra}</span></address></a>')
  36. });
  37. var SearchListView = PostListView.extend({
  38. declaredClass: 'SearchListView',
  39. view: SearchView,
  40. statusView: SearchStatusView
  41. });
  42. var renderLoading = function () {
  43. $(this.el)
  44. .toggleClass('js-loading', this.collection.state() !== 'clean')
  45. .toggleClass('js-invisible', !this.collection.length)
  46. ;
  47. return this;
  48. };
  49. var __WidgetView = WidgetView.prototype;
  50. // A view for rendering Bing views.
  51. var SearchBingView = WidgetView.extend({
  52. className: 'bing--widget cf',
  53. 'html': '<div class="bing--images"></div><div class="bing--suggestions"></div><div class="bing--results"></div>',
  54. initialize: function () {
  55. __WidgetView.initialize.apply(this, arguments);
  56. var collection = this.collection;
  57. var searchListView = new SearchListView({
  58. collection: collection
  59. });
  60. var thumbnailListView = new ThumbnailListView({
  61. collection: collection.images()
  62. });
  63. var suggestionListView = new SuggestionListView({
  64. collection: collection.suggestions()
  65. });
  66. collection.bind('state', this.render, this);
  67. this.widgets({
  68. '.bing--suggestions': suggestionListView,
  69. '.bing--results': searchListView,
  70. '.bing--images': thumbnailListView
  71. });
  72. },
  73. render: renderLoading
  74. });
  75. // Tweet View is a vanilla search view for now. May change this in future.
  76. var __SearchListView = SearchListView.prototype;
  77. var SearchTweetsView = SearchListView.extend({
  78. declaredClass: 'SearchTweetsView',
  79. initialize: function () {
  80. __SearchListView.initialize.apply(this, arguments);
  81. this.collection.bind('state', this.render, this);
  82. },
  83. render: renderLoading
  84. });
  85. var SearchTabsView = WidgetView.extend({
  86. html: '<div id="url-results"></div><div id="stack-results"></div><ul class="menu menu--modetabs pin-left"><li class="activated"><a href="#bing-results"><span class="ir ir--bing-ico">Bing</span></a></li><li><a href="#twitter-results"><span class="ir ir--twitter-ico">Twitter</span></a></li></ul><div id="bing-results"></div><div id="twitter-results"></div><div id="empty-results"></div>',
  87. events: {
  88. 'click .menu--modetabs a': 'onTabClick'
  89. },
  90. initialize: function (options) {
  91. __WidgetView.initialize.apply(this, arguments);
  92. this.panels = [
  93. '#bing-results',
  94. '#twitter-results'
  95. ];
  96. },
  97. onTabClick: function (e) {
  98. e.preventDefault();
  99. var $tab = $(e.currentTarget);
  100. this.activateTab($tab.attr('href'));
  101. this.trigger('activate', this, e);
  102. $(e.currentTarget)
  103. .parent()
  104. .addClass('activated')
  105. .siblings()
  106. .removeClass('activated');
  107. },
  108. activateTab: function (widget) {
  109. // If the widget is already active, noop.
  110. if (widget === this.active) return this;
  111. var i = util.indexOf(this.panels, widget);
  112. // If the widget ID given does not exist, let 'em know it.
  113. if (i === -1) throw new Error('No widget found for this ID');
  114. // If the referenced key is found in our panels array, move it
  115. // to the top of the array.
  116. this.panels = this.panels.splice(i, 1).concat(this.panels);
  117. // Expose active id.
  118. this.active = widget;
  119. // Toggle the views using our re-jiggered array.
  120. this.toggleViews.apply(this, this.panels);
  121. return this;
  122. },
  123. // Takes a list of widget keys. The first key will be shown.
  124. // Any keys listed after the first will be hidden.
  125. toggleViews: function (show) {
  126. // Get all arguments after the first, these are the views we should hide.
  127. var hides = slice.call(arguments, 1);
  128. $(this.widget(show).el).show();
  129. for (var i = 0; i < hides.length; i++) $(this.widget(hides[i]).el).hide();
  130. return this;
  131. }
  132. });
  133. return {
  134. SearchUrlListView: UrlListView,
  135. SearchTabsView: SearchTabsView,
  136. SearchBingView: SearchBingView,
  137. SearchTweetsView: SearchTweetsView
  138. };
  139. });