inlinedform.js 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. // A inlined form is used to provide a quick edition of single field for a given
  2. // document. Clicking on a edit button should display the form to edit the field
  3. // value. The form can then be submited, or just closed.
  4. //
  5. // When the form is closed we save non-submitted values in memory to avoid any
  6. // data loss.
  7. //
  8. // Usage:
  9. //
  10. // +inlineForm
  11. // // the content when the form is open
  12. // else
  13. // // the content when the form is close (optional)
  14. // We can only have one inlined form element opened at a time
  15. // XXX Could we avoid using a global here ? This is used in Mousetrap
  16. // keyboard.js
  17. var currentlyOpenedForm = new ReactiveVar(null);
  18. BlazeComponent.extendComponent({
  19. template: function() {
  20. return 'inlinedForm';
  21. },
  22. mixins: function() {
  23. return [Mixins.CachedValue];
  24. },
  25. onCreated: function() {
  26. this.isOpen = new ReactiveVar(false);
  27. },
  28. onDestroyed: function() {
  29. currentlyOpenedForm.set(null);
  30. },
  31. open: function() {
  32. // Close currently opened form, if any
  33. EscapeActions.executeLowerThan('inlinedForm');
  34. this.isOpen.set(true);
  35. currentlyOpenedForm.set(this);
  36. },
  37. close: function() {
  38. this.saveValue();
  39. this.isOpen.set(false);
  40. currentlyOpenedForm.set(null);
  41. },
  42. getValue: function() {
  43. var input = this.find('textarea,input[type=text]');
  44. return this.isOpen.get() && input && input.value;
  45. },
  46. saveValue: function() {
  47. this.callFirstWith(this, 'setCache', this.getValue());
  48. },
  49. events: function() {
  50. return [{
  51. 'click .js-close-inlined-form': this.close,
  52. 'click .js-open-inlined-form': this.open,
  53. // Close the inlined form by pressing escape.
  54. //
  55. // Keydown (and not keypress) in necessary here because the `keyCode`
  56. // property is consistent in all browsers, (there is not keyCode for the
  57. // `keypress` event in firefox)
  58. 'keydown form input, keydown form textarea': function(evt) {
  59. if (evt.keyCode === 27) {
  60. evt.preventDefault();
  61. EscapeActions.executeLowest();
  62. }
  63. },
  64. // Pressing Ctrl+Enter should submit the form
  65. 'keydown form textarea': function(evt) {
  66. if (evt.keyCode === 13 && (evt.metaKey || evt.ctrlKey)) {
  67. this.find('button[type=submit]').click();
  68. }
  69. },
  70. // Close the inlined form when after its submission
  71. submit: function() {
  72. var self = this;
  73. // XXX Swith to an arrow function here when we'll have ES6
  74. if (this.currentData().autoclose !== false) {
  75. Tracker.afterFlush(function() {
  76. self.close();
  77. self.callFirstWith(self, 'resetCache');
  78. });
  79. }
  80. }
  81. }];
  82. }
  83. }).register('inlinedForm');
  84. // Press escape to close the currently opened inlinedForm
  85. EscapeActions.register('inlinedForm',
  86. function() { currentlyOpenedForm.get().close(); },
  87. function() { return currentlyOpenedForm.get() !== null; }
  88. );