Browse Source

Merge pull request #169 from goto-bus-stop/feature/target-element

Accept a DOM element in `target:` and `trigger` options.
Artur Paikin 8 years ago
parent
commit
b8dc0fabbb

+ 27 - 1
src/core/Utils.js

@@ -399,6 +399,31 @@ function prettyETA (seconds) {
 //   }
 // }
 
+/**
+ * Check if an object is a DOM element. Duck-typing based on `nodeType`.
+ *
+ * @param {*} obj
+ */
+function isDOMElement (obj) {
+  return obj && typeof obj === 'object' && obj.nodeType === Node.ELEMENT_NODE
+}
+
+/**
+ * Find a DOM element.
+ *
+ * @param {Node|string} element
+ * @return {Node|null}
+ */
+function findDOMElement (element) {
+  if (typeof element === 'string') {
+    return document.querySelector(element)
+  }
+
+  if (typeof element === 'object' && isDOMElement(element)) {
+    return element
+  }
+}
+
 module.exports = {
   generateFileID,
   toArray,
@@ -423,5 +448,6 @@ module.exports = {
   // makeWorker,
   // makeCachingFunction,
   copyToClipboard,
-  prettyETA
+  prettyETA,
+  findDOMElement
 }

+ 6 - 3
src/plugins/Dashboard/ActionBrowseTagline.js

@@ -1,6 +1,11 @@
 const html = require('yo-yo')
 
 module.exports = (props) => {
+  const input = html`
+    <input class="UppyDashboard-input" type="file" name="files[]" multiple="true"
+           onchange=${props.handleInputChange} />
+  `
+
   return html`
     <span>
       ${props.acquirers.length === 0
@@ -10,11 +15,9 @@ module.exports = (props) => {
       <button type="button"
               class="UppyDashboard-browse"
               onclick=${(ev) => {
-                const input = document.querySelector(`${props.container} .UppyDashboard-input`)
                 input.click()
               }}>${props.i18n('browse')}</button>
-      <input class="UppyDashboard-input" type="file" name="files[]" multiple="true"
-             onchange=${props.handleInputChange} />
+      ${input}
     </span>
   `
 }

+ 0 - 2
src/plugins/Dashboard/Dashboard.js

@@ -77,7 +77,6 @@ module.exports = function Dashboard (props) {
           files: props.files,
           handleInputChange: handleInputChange,
           acquirers: props.acquirers,
-          container: props.container,
           panelSelectorPrefix: props.panelSelectorPrefix,
           showPanel: props.showPanel,
           i18n: props.i18n
@@ -98,7 +97,6 @@ module.exports = function Dashboard (props) {
             acquirers: props.acquirers,
             files: props.files,
             handleInputChange: handleInputChange,
-            container: props.container,
             showFileCard: props.showFileCard,
             showProgressDetails: props.showProgressDetails,
             totalProgress: props.totalProgress,

+ 0 - 1
src/plugins/Dashboard/FileList.js

@@ -12,7 +12,6 @@ module.exports = (props) => {
           <h3 class="UppyDashboard-dropFilesTitle">
             ${ActionBrowseTagline({
               acquirers: props.acquirers,
-              container: props.container,
               handleInputChange: props.handleInputChange,
               i18n: props.i18n
             })}

+ 6 - 4
src/plugins/Dashboard/Tabs.js

@@ -11,7 +11,6 @@ module.exports = (props) => {
         <h3 class="UppyDashboardTabs-title">
         ${ActionBrowseTagline({
           acquirers: props.acquirers,
-          container: props.container,
           handleInputChange: props.handleInputChange,
           i18n: props.i18n
         })}
@@ -20,6 +19,11 @@ module.exports = (props) => {
     `
   }
 
+  const input = html`
+    <input class="UppyDashboard-input" type="file" name="files[]" multiple="true"
+           onchange=${props.handleInputChange} />
+  `
+
   return html`<div class="UppyDashboardTabs">
     <nav>
       <ul class="UppyDashboardTabs-list" role="tablist">
@@ -28,14 +32,12 @@ module.exports = (props) => {
                   role="tab"
                   tabindex="0"
                   onclick=${(ev) => {
-                    const input = document.querySelector(`${props.container} .UppyDashboard-input`)
                     input.click()
                   }}>
             ${localIcon()}
             <h5 class="UppyDashboardTab-name">${props.i18n('localDisk')}</h5>
           </button>
-          <input class="UppyDashboard-input" type="file" name="files[]" multiple="true"
-                 onchange=${props.handleInputChange} />
+          ${input}
         </li>
         ${props.acquirers.map((target) => {
           return html`<li class="UppyDashboardTab">

+ 3 - 3
src/plugins/Dashboard/index.js

@@ -5,6 +5,7 @@ const Dashboard = require('./Dashboard')
 const { getSpeed } = require('../../core/Utils')
 const { getETA } = require('../../core/Utils')
 const { prettyETA } = require('../../core/Utils')
+const { findDOMElement } = require('../../core/Utils')
 const prettyBytes = require('prettier-bytes')
 const { defaultTabIcon } = require('./icons')
 
@@ -111,7 +112,7 @@ module.exports = class DashboardUI extends Plugin {
       })
     })
 
-    return this.opts.target
+    return this.target
   }
 
   hideAllPanels () {
@@ -169,7 +170,7 @@ module.exports = class DashboardUI extends Plugin {
     // const dashboardEl = document.querySelector(`${this.opts.target} .UppyDashboard`)
 
     // Modal open button
-    const showModalTrigger = document.querySelector(this.opts.trigger)
+    const showModalTrigger = findDOMElement(this.opts.trigger)
     if (!this.opts.inline && showModalTrigger) {
       showModalTrigger.addEventListener('click', this.showModal)
     } else {
@@ -380,7 +381,6 @@ module.exports = class DashboardUI extends Plugin {
       progressindicators: progressindicators,
       autoProceed: this.core.opts.autoProceed,
       id: this.id,
-      container: this.opts.target,
       hideModal: this.hideModal,
       showProgressDetails: this.opts.showProgressDetails,
       inline: this.opts.inline,

+ 2 - 2
src/plugins/DragDrop/index.js

@@ -112,7 +112,7 @@ module.exports = class DragDrop extends Plugin {
 
   render (state) {
     const onSelect = (ev) => {
-      const input = document.querySelector(`${this.target} .UppyDragDrop-input`)
+      const input = this.target.querySelector('.UppyDragDrop-input')
       input.click()
     }
 
@@ -166,7 +166,7 @@ module.exports = class DragDrop extends Plugin {
     const plugin = this
     this.target = this.mount(target, plugin)
 
-    dragDrop(`${this.target} .UppyDragDrop-container`, (files) => {
+    dragDrop(this.target.querySelector('.UppyDragDrop-container'), (files) => {
       this.handleDrop(files)
       this.core.log(files)
     })

+ 9 - 6
src/plugins/Plugin.js

@@ -1,5 +1,6 @@
 const yo = require('yo-yo')
 // const nanoraf = require('nanoraf')
+const { findDOMElement } = require('../core/Utils')
 
 /**
  * Boilerplate that all Plugins share - and should not be used
@@ -58,7 +59,7 @@ module.exports = class Plugin {
   }
 
   /**
-   * Check if supplied `target` is a `string` or an `object`.
+   * Check if supplied `target` is a DOM element or an `object`.
    * If it’s an object — target is a plugin, and we search `plugins`
    * for a plugin with same name and return its target.
    *
@@ -68,18 +69,20 @@ module.exports = class Plugin {
   mount (target, plugin) {
     const callerPluginName = plugin.id
 
-    if (typeof target === 'string') {
-      this.core.log(`Installing ${callerPluginName} to ${target}`)
+    const targetElement = findDOMElement(target)
+
+    if (targetElement) {
+      this.core.log(`Installing ${callerPluginName} to a DOM element`)
 
       // clear everything inside the target container
       if (this.opts.replaceTargetContent) {
-        document.querySelector(target).innerHTML = ''
+        targetElement.innerHTML = ''
       }
 
       this.el = plugin.render(this.core.state)
-      document.querySelector(target).appendChild(this.el)
+      targetElement.appendChild(this.el)
 
-      return target
+      return targetElement
     } else {
       // TODO: is instantiating the plugin really the way to roll
       // just to get the plugin name?