textComplete.js 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354
  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. },
  17. ...options,
  18. };
  19. // Proxy to the vanilla jQuery component
  20. this.textcomplete(strategies, options, ...otherArgs);
  21. // Since commit d474017 jquery-textComplete automatically closes a potential
  22. // opened dropdown menu when the user press Escape. This behavior conflicts
  23. // with our EscapeActions system, but it's too complicated and hacky to
  24. // monkey-pach textComplete to disable it -- I tried. Instead we listen to
  25. // 'open' and 'hide' events, and create a ghost escapeAction when the dropdown
  26. // is opened (and rely on textComplete to execute the actual action).
  27. this.on({
  28. 'textComplete:show'() {
  29. dropdownMenuIsOpened = true;
  30. },
  31. 'textComplete:hide'() {
  32. Tracker.afterFlush(() => {
  33. // XXX Hack. We unfortunately need to set a setTimeout here to make the
  34. // `noClickEscapeOn` work bellow, otherwise clicking on a autocomplete
  35. // item will close both the autocomplete menu (as expected) but also the
  36. // next item in the stack (for example the minicard editor) which we
  37. // don't want.
  38. setTimeout(() => {
  39. dropdownMenuIsOpened = false;
  40. }, 100);
  41. });
  42. },
  43. });
  44. };
  45. EscapeActions.register('textcomplete',
  46. () => {},
  47. () => dropdownMenuIsOpened, {
  48. noClickEscapeOn: '.textcomplete-dropdown',
  49. }
  50. );