index.js 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. const { BasePlugin } = require('@uppy/core')
  2. const findDOMElement = require('@uppy/utils/lib/findDOMElement')
  3. const toArray = require('@uppy/utils/lib/toArray')
  4. // Rollup uses get-form-data's ES modules build, and rollup-plugin-commonjs automatically resolves `.default`.
  5. // So, if we are being built using rollup, this require() won't have a `.default` property.
  6. const getFormData = require('get-form-data').default || require('get-form-data')
  7. /**
  8. * Form
  9. */
  10. module.exports = class Form extends BasePlugin {
  11. static VERSION = require('../package.json').version
  12. constructor (uppy, opts) {
  13. super(uppy, opts)
  14. this.type = 'acquirer'
  15. this.id = this.opts.id || 'Form'
  16. this.title = 'Form'
  17. // set default options
  18. const defaultOptions = {
  19. target: null,
  20. resultName: 'uppyResult',
  21. getMetaFromForm: true,
  22. addResultToForm: true,
  23. submitOnSuccess: false,
  24. triggerUploadOnSubmit: false,
  25. }
  26. // merge default options with the ones set by user
  27. this.opts = { ...defaultOptions, ...opts }
  28. this.handleFormSubmit = this.handleFormSubmit.bind(this)
  29. this.handleUploadStart = this.handleUploadStart.bind(this)
  30. this.handleSuccess = this.handleSuccess.bind(this)
  31. this.addResultToForm = this.addResultToForm.bind(this)
  32. this.getMetaFromForm = this.getMetaFromForm.bind(this)
  33. }
  34. handleUploadStart () {
  35. if (this.opts.getMetaFromForm) {
  36. this.getMetaFromForm()
  37. }
  38. }
  39. handleSuccess (result) {
  40. if (this.opts.addResultToForm) {
  41. this.addResultToForm(result)
  42. }
  43. if (this.opts.submitOnSuccess) {
  44. this.form.submit()
  45. }
  46. }
  47. handleFormSubmit (ev) {
  48. if (this.opts.triggerUploadOnSubmit) {
  49. ev.preventDefault()
  50. const elements = toArray(ev.target.elements)
  51. const disabledByUppy = []
  52. elements.forEach((el) => {
  53. const isButton = el.tagName === 'BUTTON' || (el.tagName === 'INPUT' && el.type === 'submit')
  54. if (isButton && !el.disabled) {
  55. el.disabled = true
  56. disabledByUppy.push(el)
  57. }
  58. })
  59. this.uppy.upload().then(() => {
  60. disabledByUppy.forEach((button) => {
  61. button.disabled = false
  62. })
  63. }, (err) => {
  64. disabledByUppy.forEach((button) => {
  65. button.disabled = false
  66. })
  67. return Promise.reject(err)
  68. }).catch((err) => {
  69. this.uppy.log(err.stack || err.message || err)
  70. })
  71. }
  72. }
  73. addResultToForm (result) {
  74. this.uppy.log('[Form] Adding result to the original form:')
  75. this.uppy.log(result)
  76. let resultInput = this.form.querySelector(`[name="${this.opts.resultName}"]`)
  77. if (resultInput) {
  78. // Append new result to the previous result array.
  79. // If the previous result is empty, or not an array,
  80. // set it to an empty array.
  81. let updatedResult
  82. try {
  83. updatedResult = JSON.parse(resultInput.value)
  84. } catch (err) {
  85. // Nothing, since we check for array below anyway
  86. }
  87. if (!Array.isArray(updatedResult)) {
  88. updatedResult = []
  89. }
  90. updatedResult.push(result)
  91. resultInput.value = JSON.stringify(updatedResult)
  92. return
  93. }
  94. resultInput = document.createElement('input')
  95. resultInput.name = this.opts.resultName
  96. resultInput.type = 'hidden'
  97. resultInput.value = JSON.stringify([result])
  98. this.form.appendChild(resultInput)
  99. }
  100. getMetaFromForm () {
  101. const formMeta = getFormData(this.form)
  102. // We want to exclude meta the the Form plugin itself has added
  103. // See https://github.com/transloadit/uppy/issues/1637
  104. delete formMeta[this.opts.resultName]
  105. this.uppy.setMeta(formMeta)
  106. }
  107. install () {
  108. this.form = findDOMElement(this.opts.target)
  109. if (!this.form || this.form.nodeName !== 'FORM') {
  110. this.uppy.log('Form plugin requires a <form> target element passed in options to operate, none was found', 'error')
  111. return
  112. }
  113. this.form.addEventListener('submit', this.handleFormSubmit)
  114. this.uppy.on('upload', this.handleUploadStart)
  115. this.uppy.on('complete', this.handleSuccess)
  116. }
  117. uninstall () {
  118. this.form.removeEventListener('submit', this.handleFormSubmit)
  119. this.uppy.off('upload', this.handleUploadStart)
  120. this.uppy.off('complete', this.handleSuccess)
  121. }
  122. }