diff --git a/client/css/forms.styl b/client/css/forms.styl
index b0c3b49..e80ac19 100644
--- a/client/css/forms.styl
+++ b/client/css/forms.styl
@@ -342,14 +342,26 @@ input::-moz-focus-inner
/*
* File dropper
*/
-.file-dropper
- background: $window-color
- border: 3px dashed #eee
- padding: 0.3em 0.5em
- line-height: 140%
- text-align: center
- cursor: pointer
- word-wrap: break-word
+.file-dropper-holder
+ display: flex
+ flex-wrap: wrap
+ .file-dropper
+ display: block
+ width: 100%
+ background: $window-color
+ border: 3px dashed #eee
+ padding: 0.3em 0.5em
+ line-height: 140%
+ text-align: center
+ cursor: pointer
+ word-wrap: break-word
+ input
+ margin-top: 0.5em
+ width: auto
+ flex: 1
+ button
+ margin-top: 0.5em
+ width: 8em
input[type=file]:disabled+.file-dropper
cursor: default
diff --git a/client/html/file_dropper.tpl b/client/html/file_dropper.tpl
index 0c052c1..eab17c6 100644
--- a/client/html/file_dropper.tpl
+++ b/client/html/file_dropper.tpl
@@ -9,4 +9,8 @@
Or just click on this box.
+ <% if (ctx.allowUrls) { %>
+
+
+ <% } %>
diff --git a/client/js/controls/file_dropper_control.js b/client/js/controls/file_dropper_control.js
index c49ff1d..300b283 100644
--- a/client/js/controls/file_dropper_control.js
+++ b/client/js/controls/file_dropper_control.js
@@ -12,11 +12,14 @@ class FileDropperControl extends events.EventTarget {
this._options = options;
const source = template({
allowMultiple: this._options.allowMultiple,
+ allowUrls: this._options.allowUrls,
id: 'file-' + Math.random().toString(36).substring(7),
});
this._dropperNode = source.querySelector('.file-dropper');
- this._fileInputNode = source.querySelector('input');
+ this._urlInputNode = source.querySelector('input[type=text]');
+ this._urlConfirmButtonNode = source.querySelector('button');
+ this._fileInputNode = source.querySelector('input[type=file]');
this._fileInputNode.style.display = 'none';
this._fileInputNode.multiple = this._options.allowMultiple || false;
@@ -32,6 +35,11 @@ class FileDropperControl extends events.EventTarget {
this._fileInputNode.addEventListener(
'change', e => this._evtFileChange(e));
+ if (this._urlInputNode) {
+ this._urlConfirmButtonNode.addEventListener(
+ 'click', e => this._evtUrlConfirm(e));
+ }
+
this._originalHtml = this._dropperNode.innerHTML;
views.replaceContent(target, source);
}
@@ -51,8 +59,18 @@ class FileDropperControl extends events.EventTarget {
new CustomEvent('fileadd', {detail: {files: files}}));
}
- _evtFileChange(e) {
- this._resolve(e.target.files);
+ _emitUrls(urls) {
+ urls = Array.from(urls).map(url => url.trim());
+ for (let url of urls) {
+ if (!url) {
+ return;
+ }
+ if (!url.match(/^https:?\/\/[^.]+\..+$/)) {
+ window.alert(`"${url}" does not look like a valid URL.`);
+ return;
+ }
+ }
+ this.dispatchEvent(new CustomEvent('urladd', {detail: {urls: urls}}));
}
_evtDragEnter(e) {
@@ -86,6 +104,13 @@ class FileDropperControl extends events.EventTarget {
}
this._emitFiles(e.dataTransfer.files);
}
+
+ _evtUrlConfirm(e) {
+ e.preventDefault();
+ this._dropperNode.classList.remove('active');
+ this._emitUrls(this._urlInputNode.value.split(/[\r\n]/));
+ this._urlInputNode.value = '';
+ }
}
module.exports = FileDropperControl;