textComplete.js 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758
  1. // We “inherit” the jquery-textcomplete plugin to integrate with our
  2. // EscapeActions system. You should always use `escapeableTextComplete` instead
  3. // of the vanilla `textcomplete`.
  4. let dropdownMenuIsOpened = false;
  5. $.fn.escapeableTextComplete = function(strategies, options, ...otherArgs) {
  6. // When the autocomplete menu is shown we want both a press of both `Tab`
  7. // or `Enter` to validation the auto-completion. We also need to stop the
  8. // event propagation to prevent EscapeActions side effect, for instance the
  9. // minicard submission (on `Enter`) or going on the next column (on `Tab`).
  10. options = {
  11. onKeydown(evt, commands) {
  12. if (evt.keyCode === 9 || evt.keyCode === 13) {
  13. evt.stopPropagation();
  14. return commands.KEY_ENTER;
  15. }
  16. return null;
  17. },
  18. ...options,
  19. };
  20. // Proxy to the vanilla jQuery component
  21. this.textcomplete(strategies, options, ...otherArgs);
  22. // Since commit d474017 jquery-textComplete automatically closes a potential
  23. // opened dropdown menu when the user press Escape. This behavior conflicts
  24. // with our EscapeActions system, but it's too complicated and hacky to
  25. // monkey-pach textComplete to disable it -- I tried. Instead we listen to
  26. // 'open' and 'hide' events, and create a ghost escapeAction when the dropdown
  27. // is opened (and rely on textComplete to execute the actual action).
  28. this.on({
  29. 'textComplete:show'() {
  30. dropdownMenuIsOpened = true;
  31. },
  32. 'textComplete:hide'() {
  33. Tracker.afterFlush(() => {
  34. // XXX Hack. We unfortunately need to set a setTimeout here to make the
  35. // `noClickEscapeOn` work bellow, otherwise clicking on a autocomplete
  36. // item will close both the autocomplete menu (as expected) but also the
  37. // next item in the stack (for example the minicard editor) which we
  38. // don't want.
  39. setTimeout(() => {
  40. dropdownMenuIsOpened = false;
  41. }, 100);
  42. });
  43. },
  44. });
  45. return this;
  46. };
  47. EscapeActions.register(
  48. 'textcomplete',
  49. () => {},
  50. () => dropdownMenuIsOpened,
  51. {
  52. noClickEscapeOn: '.textcomplete-dropdown',
  53. },
  54. );