search.js 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. document.getElementById('search_query_query').addEventListener('keydown', function (e) {
  2. if (e.keyCode === 13) {
  3. e.preventDefault();
  4. }
  5. });
  6. var searchParameters = {};
  7. if (algoliaConfig.tags) {
  8. searchParameters.disjunctiveFacets = ['tags'];
  9. searchParameters.disjunctiveFacetsRefinements = {
  10. tags: algoliaConfig.tags,
  11. };
  12. }
  13. if (algoliaConfig.type) {
  14. searchParameters.hierarchicalFacets = [{attributes: ['type'], name: 'type'}];
  15. searchParameters.hierarchicalFacetsRefinements = {
  16. type: [algoliaConfig.type],
  17. };
  18. }
  19. var searchThrottle = null;
  20. var search = instantsearch({
  21. appId: algoliaConfig.app_id,
  22. apiKey: algoliaConfig.search_key,
  23. indexName: algoliaConfig.index_name,
  24. urlSync: {
  25. trackedParameters: ['query', 'attribute:*', 'page']
  26. },
  27. searchFunction: function(helper) {
  28. var searchResults = $('#search-container');
  29. if (helper.state.query === ''
  30. && helper.state.hierarchicalFacetsRefinements.type === undefined
  31. && (helper.state.disjunctiveFacetsRefinements.tags === undefined || helper.state.disjunctiveFacetsRefinements.tags.length === 0)
  32. && algoliaConfig.tags.length === 0
  33. && algoliaConfig.type.length === 0
  34. ) {
  35. searchResults.addClass('hidden');
  36. } else {
  37. searchResults.removeClass('hidden');
  38. }
  39. if (searchThrottle) {
  40. clearTimeout(searchThrottle);
  41. }
  42. searchThrottle = setTimeout(function () {
  43. helper.search();
  44. }, 300);
  45. },
  46. searchParameters: searchParameters
  47. });
  48. search.addWidget(
  49. instantsearch.widgets.searchBox({
  50. container: '#search_query_query',
  51. magnifier: false,
  52. reset: false,
  53. wrapInput: false,
  54. autofocus: true
  55. })
  56. );
  57. search.addWidget(
  58. instantsearch.widgets.hits({
  59. container: '.search-list',
  60. transformData: function (hit) {
  61. if (hit.type === 'virtual-package') {
  62. hit.virtual = true;
  63. }
  64. return hit;
  65. },
  66. templates: {
  67. empty: 'No packages found.',
  68. item: `
  69. <div data-url="/packages/{{ name }}" class="col-xs-12 package-item">
  70. <div class="row">
  71. <div class="col-sm-9 col-lg-10">
  72. <p class="pull-right language">{{ language }}</p>
  73. <h4 class="font-bold">
  74. <a href="/packages/{{ name }}" tabindex="2">{{{ _highlightResult.name.value }}}</a>
  75. {{#virtual}}
  76. <small>(Virtual Package)</small>
  77. {{/virtual}}
  78. </h4>
  79. <p>{{{ _highlightResult.description.value }}}</p>
  80. {{#abandoned}}
  81. <p class="abandoned">
  82. <i class="glyphicon glyphicon-exclamation-sign"></i> Abandoned!
  83. {{#replacementPackage}}
  84. See <a href="/packages/{{ replacementPackage }}">{{ replacementPackage }}</a>
  85. {{/replacementPackage}}
  86. </p>
  87. {{/abandoned}}
  88. </div>
  89. <div class="col-sm-3 col-lg-2">
  90. {{#meta}}
  91. <p class="metadata">
  92. <span class="metadata-block"><i class="glyphicon glyphicon-arrow-down"></i> {{ meta.downloads_formatted }}</span>
  93. <span class="metadata-block"><i class="glyphicon glyphicon-star"></i> {{ meta.favers_formatted }}</span>
  94. </p>
  95. {{/meta}}
  96. </div>
  97. </div>
  98. </div>
  99. `
  100. },
  101. cssClasses: {
  102. root: 'packages',
  103. item: 'row'
  104. }
  105. })
  106. );
  107. search.addWidget(
  108. instantsearch.widgets.pagination({
  109. container: '.pagination',
  110. maxPages: 200,
  111. scrollTo: false,
  112. showFirstLast: false,
  113. })
  114. );
  115. search.addWidget(
  116. instantsearch.widgets.currentRefinedValues({
  117. container: '.search-facets-active-filters',
  118. clearAll: 'before',
  119. clearsQuery: false,
  120. cssClasses: {
  121. clearAll: 'pull-right'
  122. },
  123. templates: {
  124. header: 'Active filters',
  125. item: function (filter) {
  126. if ('tags' == filter.attributeName) {
  127. return 'tag: ' + filter.name
  128. } else {
  129. return filter.attributeName + ': ' + filter.name
  130. }
  131. }
  132. },
  133. onlyListedAttributes: true,
  134. })
  135. );
  136. search.addWidget(
  137. instantsearch.widgets.menu({
  138. container: '.search-facets-type',
  139. attributeName: 'type',
  140. limit: 15,
  141. showMore: true,
  142. templates: {
  143. header: 'Package type'
  144. }
  145. })
  146. );
  147. search.addWidget(
  148. instantsearch.widgets.refinementList({
  149. container: '.search-facets-tags',
  150. attributeName: 'tags',
  151. limit: 15,
  152. showMore: true,
  153. templates: {
  154. header: 'Tags'
  155. },
  156. searchForFacetValues:true
  157. })
  158. );
  159. search.start();
  160. if (algoliaConfig.tags.length || algoliaConfig.type.length) {
  161. search.helper.once('change', function (e) {
  162. window.history.replaceState(null, 'title', window.location.pathname);
  163. });
  164. }