Plugin.js 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. const yo = require('yo-yo')
  2. const nanoraf = require('nanoraf')
  3. const { findDOMElement } = require('../core/Utils')
  4. const getFormData = require('get-form-data')
  5. /**
  6. * Boilerplate that all Plugins share - and should not be used
  7. * directly. It also shows which methods final plugins should implement/override,
  8. * this deciding on structure.
  9. *
  10. * @param {object} main Uppy core object
  11. * @param {object} object with plugin options
  12. * @return {array | string} files or success/fail message
  13. */
  14. module.exports = class Plugin {
  15. constructor (core, opts) {
  16. this.core = core
  17. this.opts = opts || {}
  18. // clear everything inside the target selector
  19. // this.opts.replaceTargetContent = this.opts.replaceTargetContent !== undefined ? this.opts.replaceTargetContent : true
  20. this.update = this.update.bind(this)
  21. this.mount = this.mount.bind(this)
  22. this.install = this.install.bind(this)
  23. this.uninstall = this.uninstall.bind(this)
  24. }
  25. getPluginState () {
  26. return this.core.state.plugins[this.id]
  27. }
  28. setPluginState (update) {
  29. const plugins = Object.assign({}, this.core.state.plugins)
  30. plugins[this.id] = Object.assign({}, plugins[this.id], update)
  31. this.core.setState({
  32. plugins: plugins
  33. })
  34. }
  35. update (state) {
  36. if (typeof this.el === 'undefined') {
  37. return
  38. }
  39. if (this.updateUI) {
  40. this.updateUI(state)
  41. }
  42. }
  43. /**
  44. * Check if supplied `target` is a DOM element or an `object`.
  45. * If it’s an object — target is a plugin, and we search `plugins`
  46. * for a plugin with same name and return its target.
  47. *
  48. * @param {String|Object} target
  49. *
  50. */
  51. mount (target, plugin) {
  52. const callerPluginName = plugin.id
  53. const targetElement = findDOMElement(target)
  54. // Set up nanoraf.
  55. this.updateUI = nanoraf((state) => {
  56. this.el = yo.update(this.el, this.render(state))
  57. })
  58. if (targetElement) {
  59. this.core.log(`Installing ${callerPluginName} to a DOM element`)
  60. // attempt to extract meta from form element
  61. if (this.opts.getMetaFromForm && targetElement.nodeName === 'FORM') {
  62. const formMeta = getFormData(targetElement)
  63. this.core.setMeta(formMeta)
  64. }
  65. // clear everything inside the target container
  66. if (this.opts.replaceTargetContent) {
  67. targetElement.innerHTML = ''
  68. }
  69. this.el = plugin.render(this.core.state)
  70. targetElement.appendChild(this.el)
  71. this.target = targetElement
  72. return targetElement
  73. }
  74. let targetPlugin
  75. if (typeof target === 'object' && target instanceof Plugin) {
  76. // Targeting a plugin *instance*
  77. targetPlugin = target
  78. } else if (typeof target === 'function') {
  79. // Targeting a plugin type
  80. const Target = target
  81. // Find the target plugin instance.
  82. this.core.iteratePlugins((plugin) => {
  83. if (plugin instanceof Target) {
  84. targetPlugin = plugin
  85. return false
  86. }
  87. })
  88. }
  89. if (targetPlugin) {
  90. const targetPluginName = targetPlugin.id
  91. this.core.log(`Installing ${callerPluginName} to ${targetPluginName}`)
  92. this.target = targetPlugin
  93. return targetPlugin.addTarget(plugin)
  94. }
  95. this.core.log(`Not installing ${callerPluginName}`)
  96. throw new Error(`Invalid target option given to ${callerPluginName}`)
  97. }
  98. render (state) {
  99. throw (new Error('Extend the render method to add your plugin to a DOM element'))
  100. }
  101. addTarget (plugin) {
  102. throw (new Error('Extend the addTarget method to add your plugin to another plugin\'s target'))
  103. }
  104. unmount () {
  105. if (this.el && this.el.parentNode) {
  106. this.el.parentNode.removeChild(this.el)
  107. }
  108. this.target = null
  109. }
  110. install () {
  111. }
  112. uninstall () {
  113. this.unmount()
  114. }
  115. }