mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-05-12 17:04:57 +00:00
510 lines
12 KiB
HTML
Executable File
510 lines
12 KiB
HTML
Executable File
<!--
|
|
@license
|
|
Copyright (c) 2015 Winston Howes. All rights reserved.
|
|
This code may only be used under the MIT license found at https://github.com/winhowes/file-upload/blob/master/LICENSE
|
|
-->
|
|
<link rel="import" href="../../bower_components/polymer/polymer.html">
|
|
|
|
<!--
|
|
An element providing a solution to no problem in particular.
|
|
|
|
Example:
|
|
|
|
<file-upload target="/path/to/destination"></file-upload>
|
|
|
|
@demo
|
|
-->
|
|
|
|
<link rel="import" href="../../bower_components/paper-button/paper-button.html">
|
|
<link rel="import" href="../../bower_components/paper-progress/paper-progress.html">
|
|
<link rel="import" href="../../bower_components/iron-icons/iron-icons.html">
|
|
|
|
<dom-module id="file-upload">
|
|
|
|
<style type="text/css">
|
|
:host {
|
|
display: inline-block;
|
|
}
|
|
|
|
.enabled {
|
|
border: 1px dashed #555;
|
|
@apply(--file-upload-upload-border-enabled);
|
|
}
|
|
|
|
.hover {
|
|
opacity: .7;
|
|
border: 1px dashed #111;
|
|
@apply(--file-upload-upload-border-hover);
|
|
}
|
|
|
|
#UploadBorder{
|
|
vertical-align: middle;
|
|
color: #555;
|
|
padding: 20px;
|
|
max-height: 300px;
|
|
overflow-y: auto;
|
|
display: inline-block;
|
|
@apply(--file-upload-upload-border);
|
|
}
|
|
|
|
#dropArea {
|
|
text-align: center;
|
|
@apply(--file-upload-drop-area);
|
|
}
|
|
|
|
paper-button#button {
|
|
margin-bottom: 20px;
|
|
@apply(--file-upload-button);
|
|
}
|
|
|
|
.file {
|
|
padding: 10px 0px;
|
|
@apply(--file-upload-file);
|
|
}
|
|
|
|
.commands {
|
|
float: right;
|
|
@apply(--file-upload-commands);
|
|
}
|
|
|
|
.commands iron-icon:not([icon="check-circle"]) {
|
|
cursor: pointer;
|
|
opacity: .9;
|
|
@apply(--file-upload-commands-faded);
|
|
}
|
|
|
|
.commands iron-icon:hover {
|
|
opacity: 1;
|
|
@apply(--file-upload-commands-hovered);
|
|
}
|
|
|
|
[hidden] {
|
|
display: none;
|
|
}
|
|
|
|
.error {
|
|
color: #f40303;
|
|
font-size: 11px;
|
|
margin: 2px 0px -3px;
|
|
@apply(--file-upload-error);
|
|
}
|
|
|
|
paper-progress {
|
|
--paper-progress-active-color: #03a9f4;
|
|
}
|
|
|
|
paper-progress[error] {
|
|
--paper-progress-active-color: #f40303;
|
|
}
|
|
|
|
paper-button#button {
|
|
margin-bottom: 20px;
|
|
background-color: aquamarine;
|
|
}
|
|
</style>
|
|
|
|
<template>
|
|
<div>
|
|
<paper-button id="button" icon="file-upload" class="blue" on-click="_fileClick">
|
|
<content></content>
|
|
</paper-button>
|
|
<div id='UploadBorder'>
|
|
<div id="dropArea" hidden$="{{!_shownDropText}}">{{droptext}}</div>
|
|
<template is="dom-repeat" items="{{files}}">
|
|
<div class="file">
|
|
<div class="name">
|
|
<span>{{item.name}}</span>
|
|
<div class="commands">
|
|
<iron-icon icon="autorenew" title="{{retryText}}" on-click="_retryUpload" hidden$="{{!item.error}}"></iron-icon>
|
|
<iron-icon icon="cancel" title="{{removeText}}" on-click="_cancelUpload" hidden$="{{item.complete}}"></iron-icon>
|
|
<iron-icon icon="check-circle" title="{{successText}}" hidden$="{{!item.complete}}"></iron-icon>
|
|
</div>
|
|
</div>
|
|
<div class="error" hidden$="{{!item.error}}">{{errorText}}</div>
|
|
<div hidden$={{progressHidden}}>
|
|
<paper-progress value$="{{item.progress}}" error$="{{item.error}}"></paper-progress>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
</div>
|
|
</div>
|
|
<input type="file" id="fileInput" on-change="_fileChange" hidden multiple="{{multi}}" accept="{{accept}}">
|
|
<!--<paper-toast id="toastSuccess" text="File uploaded successfully!"></paper-toast>
|
|
<paper-toast id="toastFail" text="Error uploading file!"></paper-toast>-->
|
|
</template>
|
|
|
|
</dom-module>
|
|
|
|
<script>
|
|
|
|
Polymer({
|
|
|
|
is: 'file-upload',
|
|
|
|
/**
|
|
* Fired when a response is received status code 200.
|
|
*
|
|
* @event success
|
|
*/
|
|
/**
|
|
* Fired when a response is received other status code.
|
|
*
|
|
* @event error
|
|
*/
|
|
/**
|
|
* Fired when a file is about to be uploaded.
|
|
*
|
|
* @event before-upload
|
|
*/
|
|
|
|
properties: {
|
|
|
|
/**
|
|
* `target` is the target url to upload the files to.
|
|
* Additionally by adding "<name>" in your url, it will be replaced by
|
|
* the file name.
|
|
*/
|
|
target: {
|
|
type: String,
|
|
value: ""
|
|
},
|
|
|
|
/**
|
|
* `accept` is the set of comma separated file extensions or mime types
|
|
* to filter as accepted.
|
|
*/
|
|
|
|
accept: {
|
|
type: String,
|
|
value: ""
|
|
},
|
|
|
|
/**
|
|
* `progressHidden` indicates whether or not the progress bar should be hidden.
|
|
*/
|
|
progressHidden: {
|
|
type: Boolean,
|
|
value: false
|
|
},
|
|
|
|
/**
|
|
* `droppable` indicates whether or not to allow file drop.
|
|
*/
|
|
droppable: {
|
|
type: Boolean,
|
|
value: false,
|
|
observer: 'init'
|
|
},
|
|
|
|
/**
|
|
* `droptext` is the text to display in the file drop area.
|
|
*/
|
|
droptext: {
|
|
type: String,
|
|
value: "Drop Files Here"
|
|
},
|
|
|
|
/**
|
|
* `multi` indicates whether or not to allow multiple files to be uploaded.
|
|
*/
|
|
multi: {
|
|
type: Boolean,
|
|
value: false
|
|
},
|
|
|
|
/**
|
|
* `files` is the list of files to be uploaded
|
|
*/
|
|
files: {
|
|
type: Array,
|
|
value: function() {
|
|
return [];
|
|
}
|
|
},
|
|
|
|
/**
|
|
* `method` is the http method to be used during upload
|
|
*/
|
|
method: {
|
|
type: String,
|
|
value: "POST"
|
|
},
|
|
|
|
/**
|
|
* `raised` indicates whether or not the button should be raised
|
|
*/
|
|
raised: {
|
|
type: Boolean,
|
|
value: false
|
|
},
|
|
|
|
/**
|
|
* `noink` indicates that the button should not have an ink effect
|
|
*/
|
|
noink: {
|
|
type: Boolean,
|
|
value: false
|
|
},
|
|
|
|
/**
|
|
* `headers` is a key value map of header names and values
|
|
*/
|
|
headers: {
|
|
type: Object,
|
|
value: {},
|
|
},
|
|
|
|
/**
|
|
* `retryText` is the text for the tooltip to retry an upload
|
|
*/
|
|
retryText: {
|
|
type: String,
|
|
value: 'Retry Upload'
|
|
},
|
|
|
|
/**
|
|
* `removeText` is the text for the tooltip to remove an upload
|
|
*/
|
|
removeText: {
|
|
type: String,
|
|
value: 'Remove'
|
|
},
|
|
|
|
/**
|
|
* `successText` is the text for the tooltip of a successful upload
|
|
*/
|
|
successText: {
|
|
type: String,
|
|
value: 'Success'
|
|
},
|
|
|
|
/**
|
|
* `errorText` is the text to display for a failed upload
|
|
*/
|
|
errorText: {
|
|
type: String,
|
|
value: 'Error uploading file...'
|
|
},
|
|
|
|
/**
|
|
* `_shownDropText` indicates whether or not the drop text should be shown
|
|
*/
|
|
_shownDropText: {
|
|
type: Boolean,
|
|
value: false
|
|
},
|
|
|
|
site: {
|
|
type: String,
|
|
value: 'swsdp'
|
|
},
|
|
|
|
container: {
|
|
type: String,
|
|
value: 'documentLibrary'
|
|
},
|
|
},
|
|
|
|
/**
|
|
* Clears the list of files
|
|
*/
|
|
clear: function() {
|
|
this.set("files", []);
|
|
this._showDropText();
|
|
},
|
|
|
|
ready: function() {
|
|
},
|
|
|
|
init: function() {
|
|
if (this.raised) {
|
|
this.toggleAttribute("raised", true, this.$.button);
|
|
}
|
|
if (this.noink) {
|
|
this.toggleAttribute("noink", true, this.$.button);
|
|
}
|
|
|
|
if (this.droppable === 'true') {
|
|
this._showDropText();
|
|
this.setupDrop();
|
|
} else { this._hideDropText(); }
|
|
},
|
|
|
|
/**
|
|
* A function to set up a drop area for drag-and-drop file uploads
|
|
*/
|
|
setupDrop: function() {
|
|
var uploadBorder = this.$.UploadBorder;
|
|
this.toggleClass("enabled", true, uploadBorder);
|
|
|
|
this.ondragover = function(e) {
|
|
e.stopPropagation();
|
|
this.toggleClass("hover", true, uploadBorder);
|
|
return false;
|
|
}
|
|
|
|
this.ondragleave = function() {
|
|
this.toggleClass("hover", false, uploadBorder);
|
|
return false;
|
|
}
|
|
|
|
this.ondrop = function(event) {
|
|
this.toggleClass("hover", false, uploadBorder);
|
|
event.preventDefault();
|
|
var length = event.dataTransfer.files.length;
|
|
for (var i = 0; i < length; i++) {
|
|
var file = event.dataTransfer.files[i];
|
|
|
|
// Check if multiple upload is allowed
|
|
if (!this.multi && this.files.length !== 0) {
|
|
return;
|
|
}
|
|
|
|
// Check if filetype is accepted
|
|
var mimeType = ((file.type !== '') ? file.type.match(/^[^\/]*\//)[0] : null);
|
|
var fileType = file.name.match(/\.[^\.]*$/)[0];
|
|
if (this.accept !== '' && !(this.accept.indexOf(mimeType) > -1 || this.accept.indexOf(fileType) > -1)) {
|
|
return;
|
|
}
|
|
|
|
file.progress = 0;
|
|
file.error = false;
|
|
file.complete = false;
|
|
this.push("files", file);
|
|
this.uploadFile(file);
|
|
}
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Clicks the invisible file input
|
|
*/
|
|
_fileClick: function() {
|
|
var elem = this.$.fileInput;
|
|
if (elem && document.createEvent) { // sanity check
|
|
var evt = document.createEvent("MouseEvents");
|
|
evt.initEvent("click", true, false);
|
|
elem.dispatchEvent(evt);
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Called whenever the list of selected files changes
|
|
*/
|
|
_fileChange: function(e) {
|
|
var length = e.target.files.length;
|
|
for (var i = 0; i < length; i++) {
|
|
var file = e.target.files[i];
|
|
file.progress = 0;
|
|
file.error = false;
|
|
file.complete = false;
|
|
this.push("files", file);
|
|
this.uploadFile(file);
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Cancels the file upload for a specific file
|
|
*
|
|
* @param {object} a file, an element of the files array
|
|
*/
|
|
cancel: function(file) {
|
|
if (file && file.xhr) {
|
|
file.xhr.abort();
|
|
this.splice("files", this.files.indexOf(file), 1);
|
|
this._showDropText();
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Cancels the file upload
|
|
*
|
|
* @param {object}, an event object
|
|
*/
|
|
_cancelUpload: function(e) {
|
|
this.cancel(e.model.__data__.item);
|
|
},
|
|
|
|
/**
|
|
* Retries to upload the file
|
|
*
|
|
* @param {object}, an event object
|
|
*/
|
|
_retryUpload: function(e) {
|
|
e.model.set("item.error", false);
|
|
e.model.set("item.progress", 0);
|
|
// The async helps give visual feedback of a retry occurring, even though it's less efficient.
|
|
var self = this;
|
|
this.async(function() {
|
|
self.uploadFile(e.model.__data__.item);
|
|
}, 50);
|
|
},
|
|
|
|
/**
|
|
* Whether or not to display the drop text
|
|
*/
|
|
_showDropText: function() {
|
|
this.set("_shownDropText", true);
|
|
},
|
|
|
|
_hideDropText: function() {
|
|
this.set("_shownDropText", false);
|
|
var uploadBorder = this.$.UploadBorder;
|
|
this.toggleClass("enabled", false, uploadBorder);
|
|
this.toggleClass("hover", false, uploadBorder);
|
|
},
|
|
|
|
/**
|
|
* Uploads a file
|
|
*
|
|
* @param {object} a file, an element of the files array
|
|
*/
|
|
uploadFile: function(file) {
|
|
if (!file) {
|
|
return;
|
|
}
|
|
this.fire('before-upload');
|
|
this._showDropText();
|
|
var prefix = "files." + this.files.indexOf(file);
|
|
var self = this;
|
|
|
|
var formData = new FormData();
|
|
formData.append("filedata", file, file.name);
|
|
formData.append('siteid', this.site);
|
|
formData.append('containerid', this.container);
|
|
|
|
var xhr = file.xhr = new XMLHttpRequest();
|
|
|
|
xhr.upload.onprogress = function(e) {
|
|
var done = e.loaded, total = e.total;
|
|
self.set(prefix + ".progress", Math.floor((done/total)*1000)/10);
|
|
};
|
|
|
|
var url = this.target.replace("<name>", file.name);
|
|
xhr.open(this.method, url, true);
|
|
|
|
for (key in this.headers) {
|
|
if (this.headers.hasOwnProperty(key)) {
|
|
xhr.setRequestHeader(key, this.headers[key]);
|
|
}
|
|
}
|
|
xhr.setRequestHeader("Authorization", 'Basic ' + btoa('admin:admin'))
|
|
|
|
xhr.onload = function(e) {
|
|
if (xhr.status === 200) {
|
|
self.fire("success", {xhr: xhr});
|
|
self.set(prefix + ".complete", true);
|
|
} else {
|
|
self.set(prefix + ".error", true);
|
|
self.set(prefix + ".complete", false);
|
|
self.set(prefix + ".progress", 100);
|
|
self.updateStyles();
|
|
self.fire("error", {xhr:xhr});
|
|
}
|
|
};
|
|
xhr.send(formData);
|
|
}
|
|
});
|
|
|
|
</script>
|