You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

101 lines
3.2 KiB

  1. <template lang="pug">
  2. .nav-item
  3. p.control(v-bind:class='{ "is-loading": searchload > 0 }')
  4. input.input#search-input(type='text', v-model='searchq', autofocus, @keyup.esc='closeSearch', @keyup.down='moveDownSearch', @keyup.up='moveUpSearch', @keyup.enter='moveSelectSearch', debounce='400', v-bind:placeholder='$t("search.placeholder")')
  5. transition(name='searchresults')
  6. .searchresults(v-show='searchactive', v-cloak)
  7. p.searchresults-label {{ $t('search.results') }}
  8. ul.searchresults-list
  9. li(v-if='searchres.length === 0')
  10. a: em {{ $t('search.nomatch') }}
  11. li(v-for='sres in searchres', v-bind:class='{ "is-active": searchmovekey === "res." + sres.entryPath }')
  12. a(v-bind:href='sres.entryPath') {{ sres.title }}
  13. p.searchresults-label(v-if='searchsuggest.length > 0') {{ $t('search.didyoumean') }}
  14. ul.searchresults-list(v-if='searchsuggest.length > 0')
  15. li(v-for='sug in searchsuggest', v-bind:class='{ "is-active": searchmovekey === "sug." + sug }')
  16. a(v-on:click='useSuggestion(sug)') {{ sug }}
  17. </template>
  18. <script>
  19. export default {
  20. data() {
  21. return {
  22. searchq: '',
  23. searchres: [],
  24. searchsuggest: [],
  25. searchload: 0,
  26. searchactive: false,
  27. searchmoveidx: 0,
  28. searchmovekey: '',
  29. searchmovearr: []
  30. }
  31. },
  32. watch: {
  33. searchq: function (val, oldVal) {
  34. let self = this
  35. self.searchmoveidx = 0
  36. if (val.length >= 3) {
  37. self.searchactive = true
  38. self.searchload++
  39. socket.emit('search', { terms: val }, (data) => {
  40. self.searchres = self._.map(data.match, m => {
  41. m.entryPath = `${siteRoot}/${m.entryPath}`
  42. return m
  43. })
  44. self.searchsuggest = data.suggest
  45. self.searchmovearr = self._.concat([], self.searchres, self.searchsuggest)
  46. if (self.searchload > 0) { self.searchload-- }
  47. })
  48. } else {
  49. self.searchactive = false
  50. self.searchres = []
  51. self.searchsuggest = []
  52. self.searchmovearr = []
  53. self.searchload = 0
  54. }
  55. },
  56. searchmoveidx: function (val, oldVal) {
  57. if (val > 0) {
  58. this.searchmovekey = (this.searchmovearr[val - 1])
  59. ? 'res.' + this.searchmovearr[val - 1].entryPath
  60. : 'sug.' + this.searchmovearr[val - 1]
  61. } else {
  62. this.searchmovekey = ''
  63. }
  64. }
  65. },
  66. methods: {
  67. useSuggestion: function (sug) {
  68. this.searchq = sug
  69. },
  70. closeSearch: function () {
  71. this.searchq = ''
  72. },
  73. moveSelectSearch: function () {
  74. if (this.searchmoveidx < 1) { return }
  75. let i = this.searchmoveidx - 1
  76. if (this.searchmovearr[i]) {
  77. window.location.assign(this.searchmovearr[i].entryPath)
  78. } else {
  79. this.searchq = this.searchmovearr[i]
  80. }
  81. },
  82. moveDownSearch: function () {
  83. if (this.searchmoveidx < this.searchmovearr.length) {
  84. this.searchmoveidx++
  85. }
  86. },
  87. moveUpSearch: function () {
  88. if (this.searchmoveidx > 0) {
  89. this.searchmoveidx--
  90. }
  91. }
  92. },
  93. mounted: function () {
  94. let self = this
  95. $('main').on('click', self.closeSearch)
  96. }
  97. }
  98. </script>