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.

133 lines
4.3 KiB

  1. /**********************************************************************************
  2. *
  3. * Copyright (c) 2017-today MuK IT GmbH.
  4. *
  5. * This file is part of MuK Grid Snippets
  6. * (see https://mukit.at).
  7. *
  8. * This program is free software: you can redistribute it and/or modify
  9. * it under the terms of the GNU Lesser General Public License as published by
  10. * the Free Software Foundation, either version 3 of the License, or
  11. * (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU Lesser General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU Lesser General Public License
  19. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  20. *
  21. **********************************************************************************/
  22. odoo.define('muk_web_theme.MenuSearchMixin', function (require) {
  23. "use strict";
  24. const core = require('web.core');
  25. const config = require("web.config");
  26. const QWeb = core.qweb;
  27. const MenuSearchMixin = {
  28. _findNames(memo, menu) {
  29. if (menu.action) {
  30. const key = menu.parent_id ? menu.parent_id[1] + "/" : "";
  31. memo[key + menu.name] = menu;
  32. }
  33. if (menu.children.length) {
  34. _.reduce(menu.children, this._findNames.bind(this), memo);
  35. }
  36. return memo;
  37. },
  38. _menuInfo(key) {
  39. const original = this._searchableMenus[key];
  40. return _.extend({
  41. action_id: parseInt(original.action.split(',')[1], 10),
  42. }, original);
  43. },
  44. _searchFocus() {
  45. if (!config.device.isMobile) {
  46. this.$search_input.focus();
  47. } else {
  48. this.$search_input.blur();
  49. }
  50. },
  51. _searchReset() {
  52. this.$search_container.removeClass("has-results");
  53. this.$search_results.empty();
  54. this.$search_input.val("");
  55. },
  56. _searchMenusSchedule() {
  57. this._search_def.reject();
  58. this._search_def = $.Deferred();
  59. setTimeout(this._search_def.resolve.bind(this._search_def), 50);
  60. this._search_def.then(this._searchMenus.bind(this));
  61. },
  62. _searchMenus() {
  63. const query = this.$search_input.val();
  64. if (query === "") {
  65. this.$search_container.removeClass("has-results");
  66. this.$search_results.empty();
  67. return;
  68. }
  69. const results = fuzzy.filter(query, _.keys(this._searchableMenus), {
  70. pre: "<b>",
  71. post: "</b>",
  72. });
  73. this.$search_container.toggleClass("has-results", Boolean(results.length));
  74. this.$search_results.html(QWeb.render("muk_web_theme.MenuSearchResults", {
  75. results: results,
  76. widget: this,
  77. }));
  78. },
  79. _onSearchResultsNavigate(event) {
  80. if (this.$search_results.html().trim() === "") {
  81. this._searchMenusSchedule();
  82. return;
  83. }
  84. const all = this.$search_results.find(".mk_menu_search_result");
  85. const key = event.key || String.fromCharCode(event.which);
  86. const pre_focused = all.filter(".active") || $(all[0]);
  87. const offset = all.index(pre_focused);
  88. if (key === "Tab") {
  89. event.preventDefault();
  90. key = event.shiftKey ? "ArrowUp" : "ArrowDown";
  91. }
  92. switch (key) {
  93. case "Enter":
  94. pre_focused.click();
  95. break;
  96. case "ArrowUp":
  97. offset--;
  98. break;
  99. case "ArrowDown":
  100. offset++;
  101. break;
  102. default:
  103. this._searchMenusSchedule();
  104. return;
  105. }
  106. if (offset < 0) {
  107. offset = all.length + offset;
  108. } else if (offset >= all.length) {
  109. offset -= all.length;
  110. }
  111. const new_focused = $(all[offset]);
  112. pre_focused.removeClass("active");
  113. new_focused.addClass("active");
  114. this.$search_results.scrollTo(new_focused, {
  115. offset: {
  116. top: this.$search_results.height() * -0.5,
  117. },
  118. });
  119. },
  120. _onMenuShown(event) {
  121. this._searchFocus();
  122. },
  123. _onMenuHidden(event) {
  124. this._searchReset();
  125. },
  126. };
  127. return MenuSearchMixin;
  128. });