modal.component.js 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. /**
  2. * <modal>
  3. * -----------------------------------------------------------------------------
  4. * A modal dialog pop-up.
  5. *
  6. * @type {Component}
  7. *
  8. * @event close [emitted when the closing process begins]
  9. * @event opened [emitted when the opening process is completely done]
  10. * -----------------------------------------------------------------------------
  11. */
  12. parasails.registerComponent('modal', {
  13. // ╔═╗╦═╗╔═╗╔═╗╔═╗
  14. // ╠═╝╠╦╝║ ║╠═╝╚═╗
  15. // ╩ ╩╚═╚═╝╩ ╚═╝
  16. props: [
  17. 'large'
  18. ],
  19. // ╦╔╗╔╦╔╦╗╦╔═╗╦ ╔═╗╔╦╗╔═╗╔╦╗╔═╗
  20. // ║║║║║ ║ ║╠═╣║ ╚═╗ ║ ╠═╣ ║ ║╣
  21. // ╩╝╚╝╩ ╩ ╩╩ ╩╩═╝ ╚═╝ ╩ ╩ ╩ ╩ ╚═╝
  22. data: function (){
  23. return {
  24. // Spinlock used for preventing trying to close the bootstrap modal more than once.
  25. // (in practice it doesn't seem to hurt anything if it tries to close more than once,
  26. // but still.... better safe than sorry!)
  27. _bsModalIsAnimatingOut: false
  28. };
  29. },
  30. // ╦ ╦╔╦╗╔╦╗╦
  31. // ╠═╣ ║ ║║║║
  32. // ╩ ╩ ╩ ╩ ╩╩═╝
  33. template: `
  34. <transition name="modal" v-on:leave="leave" v-bind:css="false">
  35. <div class="modal fade clog-modal" tabindex="-1" role="dialog">
  36. <div class="petticoat"></div>
  37. <div class="modal-dialog custom-width" :class="large ? 'modal-lg' : ''" role="document">
  38. <div class="modal-content">
  39. <slot></slot>
  40. </div><!-- /.modal-content -->
  41. </div><!-- /.modal-dialog -->
  42. </div><!-- /.modal -->
  43. </transition>
  44. `,
  45. // ╦ ╦╔═╗╔═╗╔═╗╦ ╦╔═╗╦ ╔═╗
  46. // ║ ║╠╣ ║╣ ║ ╚╦╝║ ║ ║╣
  47. // ╩═╝╩╚ ╚═╝╚═╝ ╩ ╚═╝╩═╝╚═╝
  48. mounted: function (){
  49. // Immediately call out to the Bootstrap modal and tell it to show itself.
  50. $(this.$el).modal({
  51. // Set the modal backdrop to the 'static' option, which means it doesn't close the modal
  52. // when clicked.
  53. backdrop: 'static',
  54. show: true
  55. });
  56. // Attach listener for underlying custom modal closing event,
  57. // and when that happens, have Vue emit a custom "close" event.
  58. // (Note: This isn't just for convenience-- it's crucial that
  59. // the parent logic can use this event to update its scope.)
  60. $(this.$el).on('hide.bs.modal', ()=>{
  61. this._bsModalIsAnimatingOut = true;
  62. this.$emit('close');
  63. });//ƒ
  64. // Attach listener for underlying custom modal "opened" event,
  65. // and when that happens, have Vue emit our own custom "opened" event.
  66. // This is so we know when the entry animation has completed, allows
  67. // us to do cool things like auto-focus the first input in a form modal.
  68. $(this.$el).on('shown.bs.modal', ()=>{
  69. this.$emit('opened');
  70. $(this.$el).off('shown.bs.modal');
  71. });//ƒ
  72. },
  73. // ╦╔╗╔╔╦╗╔═╗╦═╗╔═╗╔═╗╔╦╗╦╔═╗╔╗╔╔═╗
  74. // ║║║║ ║ ║╣ ╠╦╝╠═╣║ ║ ║║ ║║║║╚═╗
  75. // ╩╝╚╝ ╩ ╚═╝╩╚═╩ ╩╚═╝ ╩ ╩╚═╝╝╚╝╚═╝
  76. methods: {
  77. leave: function (el, done) {
  78. // If this shutting down was spawned by the bootstrap modal's built-in logic,
  79. // then we'll have already begun animating the modal shut. So we check our
  80. // spinlock to make sure. If it turns out that we HAVEN'T started that process
  81. // yet, then we go ahead and start it now.
  82. if (!this._bsModalIsAnimatingOut) {
  83. $(this.$el).modal('hide');
  84. }//fi
  85. // When the bootstrap modal finishes animating into nothingness, unbind all
  86. // the DOM events used by bootstrap, and then call `done()`, which passes
  87. // control back to Vue and lets it finish the job (i.e. afterLeave).
  88. //
  89. // > Note that the other lifecycle events like `destroyed` were actually
  90. // > already fired at this point.
  91. // >
  92. // > Also note that, since we're potentially long past the `destroyed` point
  93. // > of the lifecycle here, we can't call `.$emit()` anymore either. So,
  94. // > for example, we wouldn't be able to emit a "fullyClosed" event --
  95. // > because by the time it'd be appropriate to emit the Vue event, our
  96. // > context for triggering it (i.e. the relevant instance of this component)
  97. // > will no longer be capable of emitting custom Vue events (because by then,
  98. // > it is no longer "reactive").
  99. // >
  100. // > For more info, see:
  101. // > https://github.com/vuejs/vue-router/issues/1302#issuecomment-291207073
  102. $(this.$el).on('hidden.bs.modal', ()=>{
  103. $(this.$el).off('hide.bs.modal');
  104. $(this.$el).off('hidden.bs.modal');
  105. $(this.$el).off('shown.bs.modal');
  106. done();
  107. });//_∏_
  108. },
  109. }
  110. });