JSFiddle - React, Tailwind, and code Playground
by Graham Dixon
HTML
<script src="https://cdnjs.cloudflare.com/ajax/libs/localforage/1.7.1/localforage.js"></script>
<div class="container" role="main" class="box">
<form method="post" id='file-catcher' action="?" enctype="multipart/form-data" novalidate fileStoreName="testing">
<div class="box__input">
<svg class="box__icon" xmlns="http://www.w3.org/2000/svg" width="50" height="43" viewBox="0 0 50 43"><path d="M48.4 26.5c-.9 0-1.7.7-1.7 1.7v11.6h-43.3v-11.6c0-.9-.7-1.7-1.7-1.7s-1.7.7-1.7 1.7v13.2c0 .9.7 1.7 1.7 1.7h46.7c.9 0 1.7-.7 1.7-1.7v-13.2c0-1-.7-1.7-1.7-1.7zm-24.5 6.1c.3.3.8.5 1.2.5.4 0 .9-.2 1.2-.5l10-11.6c.7-.7.7-1.7 0-2.4s-1.7-.7-2.4 0l-7.1 8.3v-25.3c0-.9-.7-1.7-1.7-1.7s-1.7.7-1.7 1.7v25.3l-7.1-8.3c-.7-.7-1.7-.7-2.4 0s-.7 1.7 0 2.4l10 11.6z"/></svg>
<label for="file"><strong>Choose a file</strong><span class="box__dragndrop"> or drag it here</span>.<br/></label>
<input id='file-input' type='file' multiple/>
<button type='submit' class='box___button' >
Submit
</button>
</div>
<div class="box__uploading">Uploading…</div>
<div class="box__success">Done! <a href="?" class="box__restart" role="button">Upload more?</a></div>
<div class="box__error">Error! <span></span>. <a href="?" class="box__restart" role="button">Try again!</a></div>
</form>
<div id='file-list-display'></div>
</div>
CSS
html {}
body {
font-family: Roboto, sans-serif;
color: #0f3c4b;
background-color: #e5edf1;
padding: 5rem 1.25rem;
/* 80 20 */
}
.container {
width: 100%;
max-width: 680px;
/* 800 */
text-align: center;
margin: 0 auto;
}
.container h1 {
font-size: 42px;
font-weight: 300;
color: #0f3c4b;
margin-bottom: 40px;
}
.container h1 a:hover,
.container h1 a:focus {
color: #39bfd3;
}
.container nav {
margin-bottom: 40px;
}
.container nav a {
border-bottom: 2px solid #c8dadf;
display: inline-block;
padding: 4px 8px;
margin: 0 5px;
}
.container nav a.is-selected {
font-weight: 700;
color: #39bfd3;
border-bottom-color: currentColor;
}
.container nav a:not( .is-selected):hover,
.container nav a:not( .is-selected):focus {
border-bottom-color: #0f3c4b;
}
.container footer {
color: #92b0b3;
margin-top: 40px;
}
.container footer p+p {
margin-top: 1em;
}
.container footer a:hover,
.container footer a:focus {
color: #39bfd3;
}
.box {
font-size: 1.25rem;
/* 20 */
background-color: #c8dadf;
position: relative;
padding: 100px 20px;
}
.box.has-advanced-upload {
outline: 2px dashed #92b0b3;
outline-offset: -10px;
-webkit-transition: outline-offset .15s ease-in-out, background-color .15s linear;
transition: outline-offset .15s ease-in-out, background-color .15s linear;
}
.box.is-dragover {
outline-offset: -20px;
outline-color: #c8dadf;
background-color: #fff;
}
.box__dragndrop,
.box__icon {
display: none;
}
.box.has-advanced-upload .box__dragndrop {
display: inline;
}
.box.has-advanced-upload .box__icon {
width: 100%;
height: 80px;
fill: #92b0b3;
display: block;
margin-bottom: 40px;
}
.box__input {
text-align: left
}
.box.is-uploading .box__input,
.box.is-success...
JavaScript
/*!
* Script: jQuery.fileCatcher.js
* Description: jQuery.fileCatcher - A jQuery plugin...
* Copyright: Copyright (c) 2018 Money Marketplace LTD
* Author: GDixon
* Email: [email protected]
* Licensed: MIT
* Requires: jQuery > 1.9
* Version: 0.0.1
*/
;
(function(factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module depending on jQuery
define(['jquery'], factory);
} else {
// No AMD. Register plugin with global jQuery object
factory(jQuery);
}
} (
function($) {
// defaults to align the repeatable instance with the dom situation
var defaults = {
dataAttr: "fileCatcher",
storeAttr: "fileStoreName"
};
$.fn.fileCatcher = (function(options, data) {
// the options must be passed to the init func as an array - convert any strings
var optionsArray = (typeof options == "string" ? [options] : options);
// only create when the giving el exists
if ($(this).length) {
// extend defaults with options and set to settings
optionsArray = $.extend({}, defaults, (typeof optionsArray !== "undefined" ? optionsArray : []));
// check that repeatable instance hasnt already been created against instance
if (typeof $(this).data(optionsArray.dataAttr) == "undefined") {
// create a new instance
var instance = $(this).data(optionsArray.dataAttr, new FileCatcher(this, optionsArray, data)).data(optionsArray.dataAttr);
} else {
// do option based functions
if (typeof options !== 'undefined' && options == "destroy") {
// fully destroys the repeatable instance
var instance = this.data(optionsArray.dataAttr).destroy();
} else if (typeof options !== 'undefined') {
// recreates the...