PageRenderTime 42ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

/public/js/app/views/SearchCardsView.js

https://github.com/Reflen/spinel
JavaScript | 184 lines | 147 code | 32 blank | 5 comment | 18 complexity | 00382ea69731d28e34c813cfa9f99930 MD5 | raw file
  1. // SearchCardsView.js
  2. // -------
  3. define(["jquery", "backbone", "collections/GenericCollection",
  4. "./BaseView", "views/SearchCardItemView"
  5. ],
  6. function($, Backbone, Collection,
  7. BaseView, SearchCardItemView) {
  8. var View = BaseView.extend({
  9. el: "#find-results",
  10. tagName: "div",
  11. className: "autocomplete",
  12. wait: 300,
  13. queryParameter: "q",
  14. minKeywordLength: 2,
  15. currentText: "",
  16. itemView: SearchCardItemView,
  17. initialize: function(context) {
  18. _.extend(this, context);
  19. this.collection = new Collection({
  20. query: "search"
  21. });
  22. this.filter = _.debounce(this.filter, this.wait);
  23. if (this.query) {
  24. this.filter(this.query);
  25. this.input.attr("placeholder", this.query);
  26. }
  27. },
  28. events: {
  29. "click .tag": "showTopic",
  30. "click .work-on-project": "lunchProject"
  31. },
  32. showTopic: function(e) {
  33. e.stopPropagation();
  34. var topic = {
  35. "id": e.currentTarget.getAttribute('data-topic-id'),
  36. "name": e.currentTarget.getAttribute('data-topic-name')
  37. };
  38. this.pubsub.trigger("action:showGraph", topic);
  39. },
  40. lunchProject: function(e) {
  41. e.stopPropagation();
  42. var id = e.currentTarget.getAttribute('data-project-id');
  43. Backbone.history.navigate(id, {
  44. trigger: true
  45. });
  46. },
  47. render: function() {
  48. // disable the native auto complete functionality
  49. this.input.attr("autocomplete", "off");
  50. this.input
  51. .keyup(_.bind(this.keyup, this))
  52. .keydown(_.bind(this.keydown, this));
  53. return this;
  54. },
  55. keydown: function(event) {
  56. if (event.keyCode == 38) return this.move(-1);
  57. if (event.keyCode == 40) return this.move(+1);
  58. if (event.keyCode == 13) return this.onEnter();
  59. if (event.keyCode == 27) return this.hide();
  60. },
  61. keyup: function() {
  62. var keyword = this.input.val();
  63. if (this.isChanged(keyword)) {
  64. if (this.isValid(keyword)) {
  65. this.filter(keyword);
  66. } else {
  67. this.hide();
  68. }
  69. }
  70. },
  71. updateSearchUrl: function(query) {
  72. Backbone.history.navigate('search/' + query);
  73. },
  74. filter: function(origKeyword) {
  75. var keyword = origKeyword.toLowerCase();
  76. if (this.collection.url) {
  77. var parameters = {};
  78. parameters[this.queryParameter] = keyword;
  79. this.collection.fetch({
  80. success: function() {
  81. this.updateSearchUrl(keyword);
  82. this.loadResult(this.collection.models, keyword);
  83. }.bind(this),
  84. data: parameters
  85. });
  86. } else {
  87. this.loadResult(this.collection.filter(function(model) {
  88. return model.label().toLowerCase().indexOf(keyword) !== -1;
  89. }), keyword);
  90. }
  91. },
  92. isValid: function(keyword) {
  93. return keyword.length > this.minKeywordLength;
  94. },
  95. isChanged: function(keyword) {
  96. return this.currentText != keyword;
  97. },
  98. move: function(position) {
  99. var current = this.$el.children(".active"),
  100. siblings = this.$el.children(),
  101. index = current.index() + position;
  102. if (siblings.eq(index).length) {
  103. current.removeClass("active");
  104. siblings.eq(index).addClass("active");
  105. }
  106. return false;
  107. },
  108. onEnter: function() {
  109. this.$el.children(".active").click();
  110. return false;
  111. },
  112. loadResult: function(model, keyword) {
  113. this.currentText = keyword;
  114. this.show().reset();
  115. if (model.length) {
  116. _.forEach(model, this.addItem, this);
  117. this.show();
  118. } else {
  119. this.hide();
  120. }
  121. },
  122. addItem: function(model) {
  123. this.$el.append(new this.itemView({
  124. model: model,
  125. parent: this
  126. }).render().$el);
  127. },
  128. select: function(model) {
  129. var label = model.label();
  130. this.input.val(label);
  131. this.currentText = label;
  132. this.onSelect(model);
  133. },
  134. reset: function() {
  135. this.$el.empty();
  136. return this;
  137. },
  138. hide: function() {
  139. this.$el.hide();
  140. return this;
  141. },
  142. show: function() {
  143. this.$el.show();
  144. return this;
  145. },
  146. // callback definitions
  147. onSelect: function() {}
  148. });
  149. // Returns the View class
  150. return View;
  151. }
  152. );