Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

120 lines
3.1KB

  1. fetchInject([
  2. "{{ "/js/vue.min.js" | relURL }}",
  3. "{{ "/js/lodash.custom.min.js" | relURL }}",
  4. "{{ "/js/fuse.min.js" | relURL }}",
  5. "{{ "/js/mark.min.js" | relURL }}"
  6. ]).then(() => {
  7. (function (window, document, undefined) {
  8. 'use strict';
  9. const getQueryByParam = param => decodeURIComponent(
  10. (location.search.split(param + '=')[1] || '').split('&')[0]
  11. ).replace(/\+/g, ' ');
  12. const queryParam = 's';
  13. const selectors = {
  14. appContainer: '#search-app',
  15. resultContainer: '#search-results',
  16. searchInput: '#query'
  17. };
  18. const fuseOpts = {
  19. shouldSort: true,
  20. tokenize: true,
  21. matchAllTokens: true,
  22. includeScore: true,
  23. includeMatches: true,
  24. keys: [
  25. { name: "title", weight: 0.8 },
  26. { name: "contents", weight: 0.5 },
  27. { name: "tags", weight: 0.3 },
  28. { name: "categories", weight: 0.3 }
  29. ]
  30. };
  31. const getSearchInput = () => document.querySelector(selectors.searchInput);
  32. const focusSearchInput = () => getSearchInput().focus();
  33. const searchQuery = getSearchInput().value = getQueryByParam(queryParam);
  34. const fuse = new Fuse([], fuseOpts);
  35. window.fetch('/index.json').then(response => {
  36. response.text().then(searchData => {
  37. fuse.setCollection(JSON.parse(searchData));
  38. searchQuery && search(searchQuery);
  39. });
  40. });
  41. const getUrl = (query) => {
  42. const encodedQuery = encodeURIComponent(query);
  43. const url = "{{ .URL }}";
  44. return (encodedQuery)
  45. ? `${url}?${queryParam}=${encodedQuery}`
  46. : url;
  47. };
  48. let mark = new Mark(
  49. document.querySelector(
  50. selectors.resultContainer
  51. )
  52. );
  53. const app = new Vue({
  54. delimiters: ['{', '}'],
  55. el: selectors.appContainer,
  56. data: {
  57. fuse: null,
  58. results: [],
  59. query: getQueryByParam(queryParam),
  60. resultsForSearch: getQueryByParam(queryParam)
  61. },
  62. mounted () {
  63. this.fuse = fuse;
  64. window.onpopstate = (evt) => {
  65. this.query = evt.state.query;
  66. };
  67. document.onkeyup = function (evt) {
  68. evt.key === 's' && focusSearchInput();
  69. }
  70. focusSearchInput();
  71. },
  72. watch: {
  73. query () {
  74. this.executeSearch();
  75. window.history.replaceState(
  76. {query: this.query},
  77. null,
  78. getUrl(this.query)
  79. );
  80. }
  81. },
  82. beforeUpdate: function () {
  83. mark.unmark();
  84. },
  85. updated: function () {
  86. this.$nextTick(function () {
  87. mark = new Mark(
  88. document.querySelector(
  89. selectors.resultContainer
  90. )
  91. )
  92. mark.mark(this.query.trim());
  93. })
  94. },
  95. methods: {
  96. executeSearch: _.debounce(function () {
  97. const trimmedQuery = this.query.trim();
  98. this.resultsForSearch = trimmedQuery;
  99. this.results = (trimmedQuery)
  100. ? this.fuse.search(trimmedQuery)
  101. : [];
  102. }, 250)
  103. }
  104. });
  105. const search = query => {
  106. app.results = fuse.search(query);
  107. };
  108. })(window, document);
  109. });