A pure Javascript file upload with drop zone (drag & drop) and image preview.
- No Jquery or Plugins required.
A Pen by Matt Litherland on CodePen.
A pure Javascript file upload with drop zone (drag & drop) and image preview.
A Pen by Matt Litherland on CodePen.
| <h2>File Upload & Image Preview</h2> | |
| <p class="lead">No Plugins <b>Just Javascript</b></p> | |
| <!-- Upload --> | |
| <form id="file-upload-form" class="uploader"> | |
| <input id="file-upload" type="file" name="fileUpload" accept="image/*" /> | |
| <label for="file-upload" id="file-drag"> | |
| <img id="file-image" src="#" alt="Preview" class="hidden"> | |
| <div id="start"> | |
| <i class="fa fa-download" aria-hidden="true"></i> | |
| <div>Select a file or drag here</div> | |
| <div id="notimage" class="hidden">Please select an image</div> | |
| <span id="file-upload-btn" class="btn btn-primary">Select a file</span> | |
| </div> | |
| <div id="response" class="hidden"> | |
| <div id="messages"></div> | |
| <progress class="progress" id="file-progress" value="0"> | |
| <span>0</span>% | |
| </progress> | |
| </div> | |
| </label> | |
| </form> |
| // File Upload | |
| // | |
| function ekUpload(){ | |
| function Init() { | |
| console.log("Upload Initialised"); | |
| var fileSelect = document.getElementById('file-upload'), | |
| fileDrag = document.getElementById('file-drag'), | |
| submitButton = document.getElementById('submit-button'); | |
| fileSelect.addEventListener('change', fileSelectHandler, false); | |
| // Is XHR2 available? | |
| var xhr = new XMLHttpRequest(); | |
| if (xhr.upload) { | |
| // File Drop | |
| fileDrag.addEventListener('dragover', fileDragHover, false); | |
| fileDrag.addEventListener('dragleave', fileDragHover, false); | |
| fileDrag.addEventListener('drop', fileSelectHandler, false); | |
| } | |
| } | |
| function fileDragHover(e) { | |
| var fileDrag = document.getElementById('file-drag'); | |
| e.stopPropagation(); | |
| e.preventDefault(); | |
| fileDrag.className = (e.type === 'dragover' ? 'hover' : 'modal-body file-upload'); | |
| } | |
| function fileSelectHandler(e) { | |
| // Fetch FileList object | |
| var files = e.target.files || e.dataTransfer.files; | |
| // Cancel event and hover styling | |
| fileDragHover(e); | |
| // Process all File objects | |
| for (var i = 0, f; f = files[i]; i++) { | |
| parseFile(f); | |
| uploadFile(f); | |
| } | |
| } | |
| // Output | |
| function output(msg) { | |
| // Response | |
| var m = document.getElementById('messages'); | |
| m.innerHTML = msg; | |
| } | |
| function parseFile(file) { | |
| console.log(file.name); | |
| output( | |
| '<strong>' + encodeURI(file.name) + '</strong>' | |
| ); | |
| // var fileType = file.type; | |
| // console.log(fileType); | |
| var imageName = file.name; | |
| var isGood = (/\.(?=gif|jpg|png|jpeg)/gi).test(imageName); | |
| if (isGood) { | |
| document.getElementById('start').classList.add("hidden"); | |
| document.getElementById('response').classList.remove("hidden"); | |
| document.getElementById('notimage').classList.add("hidden"); | |
| // Thumbnail Preview | |
| document.getElementById('file-image').classList.remove("hidden"); | |
| document.getElementById('file-image').src = URL.createObjectURL(file); | |
| } | |
| else { | |
| document.getElementById('file-image').classList.add("hidden"); | |
| document.getElementById('notimage').classList.remove("hidden"); | |
| document.getElementById('start').classList.remove("hidden"); | |
| document.getElementById('response').classList.add("hidden"); | |
| document.getElementById("file-upload-form").reset(); | |
| } | |
| } | |
| function setProgressMaxValue(e) { | |
| var pBar = document.getElementById('file-progress'); | |
| if (e.lengthComputable) { | |
| pBar.max = e.total; | |
| } | |
| } | |
| function updateFileProgress(e) { | |
| var pBar = document.getElementById('file-progress'); | |
| if (e.lengthComputable) { | |
| pBar.value = e.loaded; | |
| } | |
| } | |
| function uploadFile(file) { | |
| var xhr = new XMLHttpRequest(), | |
| fileInput = document.getElementById('class-roster-file'), | |
| pBar = document.getElementById('file-progress'), | |
| fileSizeLimit = 1024; // In MB | |
| if (xhr.upload) { | |
| // Check if file is less than x MB | |
| if (file.size <= fileSizeLimit * 1024 * 1024) { | |
| // Progress bar | |
| pBar.style.display = 'inline'; | |
| xhr.upload.addEventListener('loadstart', setProgressMaxValue, false); | |
| xhr.upload.addEventListener('progress', updateFileProgress, false); | |
| // File received / failed | |
| xhr.onreadystatechange = function(e) { | |
| if (xhr.readyState == 4) { | |
| // Everything is good! | |
| // progress.className = (xhr.status == 200 ? "success" : "failure"); | |
| // document.location.reload(true); | |
| } | |
| }; | |
| // Start upload | |
| xhr.open('POST', document.getElementById('file-upload-form').action, true); | |
| xhr.setRequestHeader('X-File-Name', file.name); | |
| xhr.setRequestHeader('X-File-Size', file.size); | |
| xhr.setRequestHeader('Content-Type', 'multipart/form-data'); | |
| xhr.send(file); | |
| } else { | |
| output('Please upload a smaller file (< ' + fileSizeLimit + ' MB).'); | |
| } | |
| } | |
| } | |
| // Check for the various File API support. | |
| if (window.File && window.FileList && window.FileReader) { | |
| Init(); | |
| } else { | |
| document.getElementById('file-drag').style.display = 'none'; | |
| } | |
| } | |
| ekUpload(); |
| <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script> |
| // Imports | |
| // | |
| @import url(https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css); | |
| @import url('https://fonts.googleapis.com/css?family=Roboto'); | |
| // Vars and Reset | |
| // | |
| $theme: #454cad; | |
| $dark-text: #5f6982; | |
| html,body,* { box-sizing: border-box; font-size: 16px;} | |
| html,body { height: 100%; text-align: center;} | |
| body { padding: 2rem; background: #f8f8f8;} | |
| h2 { | |
| font-family: "Roboto", sans-serif; | |
| font-size: 26px; | |
| line-height: 1; | |
| color: $theme; | |
| margin-bottom: 0; | |
| } | |
| p { | |
| font-family: "Roboto", sans-serif; | |
| font-size: 18px; | |
| color: $dark-text; | |
| } | |
| // Upload Demo | |
| // | |
| .uploader { | |
| display: block; | |
| clear: both; | |
| margin: 0 auto; | |
| width: 100%; | |
| max-width: 600px; | |
| label { | |
| float: left; | |
| clear: both; | |
| width: 100%; | |
| padding: 2rem 1.5rem; | |
| text-align: center; | |
| background: #fff; | |
| border-radius: 7px; | |
| border: 3px solid #eee; | |
| transition: all .2s ease; | |
| user-select: none; | |
| &:hover { | |
| border-color: $theme; | |
| } | |
| &.hover { | |
| border: 3px solid $theme; | |
| box-shadow: inset 0 0 0 6px #eee; | |
| #start { | |
| i.fa { | |
| transform: scale(0.8); | |
| opacity: 0.3; | |
| } | |
| } | |
| } | |
| } | |
| #start { | |
| float: left; | |
| clear: both; | |
| width: 100%; | |
| &.hidden { | |
| display: none; | |
| } | |
| i.fa { | |
| font-size: 50px; | |
| margin-bottom: 1rem; | |
| transition: all .2s ease-in-out; | |
| } | |
| } | |
| #response { | |
| float: left; | |
| clear: both; | |
| width: 100%; | |
| &.hidden { | |
| display: none; | |
| } | |
| #messages { | |
| margin-bottom: .5rem; | |
| } | |
| } | |
| #file-image { | |
| display: inline; | |
| margin: 0 auto .5rem auto; | |
| width: auto; | |
| height: auto; | |
| max-width: 180px; | |
| &.hidden { | |
| display: none; | |
| } | |
| } | |
| #notimage { | |
| display: block; | |
| float: left; | |
| clear: both; | |
| width: 100%; | |
| &.hidden { | |
| display: none; | |
| } | |
| } | |
| progress, | |
| .progress { | |
| // appearance: none; | |
| display: inline; | |
| clear: both; | |
| margin: 0 auto; | |
| width: 100%; | |
| max-width: 180px; | |
| height: 8px; | |
| border: 0; | |
| border-radius: 4px; | |
| background-color: #eee; | |
| overflow: hidden; | |
| } | |
| .progress[value]::-webkit-progress-bar { | |
| border-radius: 4px; | |
| background-color: #eee; | |
| } | |
| .progress[value]::-webkit-progress-value { | |
| background: linear-gradient(to right, darken($theme,8%) 0%, $theme 50%); | |
| border-radius: 4px; | |
| } | |
| .progress[value]::-moz-progress-bar { | |
| background: linear-gradient(to right, darken($theme,8%) 0%, $theme 50%); | |
| border-radius: 4px; | |
| } | |
| input[type="file"] { | |
| display: none; | |
| } | |
| div { | |
| margin: 0 0 .5rem 0; | |
| color: $dark-text; | |
| } | |
| .btn { | |
| display: inline-block; | |
| margin: .5rem .5rem 1rem .5rem; | |
| clear: both; | |
| font-family: inherit; | |
| font-weight: 700; | |
| font-size: 14px; | |
| text-decoration: none; | |
| text-transform: initial; | |
| border: none; | |
| border-radius: .2rem; | |
| outline: none; | |
| padding: 0 1rem; | |
| height: 36px; | |
| line-height: 36px; | |
| color: #fff; | |
| transition: all 0.2s ease-in-out; | |
| box-sizing: border-box; | |
| background: $theme; | |
| border-color: $theme; | |
| cursor: pointer; | |
| } | |
| } |