Fork me on GitHub
Upload.js
A simple and clean HTML5, dependency free, image uploader and remover

Demo

See Upload.js in action


Basic To get started as quickly as possible add the DIV element, find in your script and call UploadJs

Copy
<div id="upload-demo-1" data-upload-url="/upload" data-upload-delete-url="/delete"></div>
Copy
var div = document.getElementById("upload-demo-1");
new UploadJs(div);

With Existing You can define UploadJS with images already populated.

Copy
<div id="upload-demo-2" data-upload-url="/upload" data-upload-delete-url="/delete">
    <img src="existing-img-1.jpg" data-upload-image-id="1" />
    <img src="existing-img-2.jpg" data-upload-image-id="2" />
</div>
Copy
var div = document.getElementById("upload-demo-2");
new UploadJs(div);

Set Maximum You can define UploadJs so that it allows fixed number of images.

Copy
<div id="upload-demo-3" data-upload-url="/upload" data-upload-delete-url="/delete" data-upload-max="1"></div>
Copy
var div = document.getElementById("upload-demo-3");
new UploadJs(div);

Not deletable You can define UploadJs so that images are not deletable.

Copy
<div id="upload-demo-4" data-upload-url="/upload" data-upload-deletable="false">
    <img src="existing-img-1.jpg" data-upload-image-id="1" />
</div>
Copy
var div = document.getElementById("upload-demo-4");
new UploadJs(div);
You can make individual images not deletable by not defining data-upload-image-id=".." for existing img tags instead of defining data-upload-deletable="false" on the div element
Instead of:
<img src="existing-img-1.jpg" data-upload-image-id="1" />
Define as:
<img src="existing-img-1.jpg" />
For images that are uploaded through UploadJs the return JSON should not define the uploadImageId field
Instead of:
{success: "true", uploadImageId: "1"}
Define as:
{success: "true"}

Icons You can change the default icons used for UploadJs. You can either use Font Awesome or Glyphicons.

Font Awesome:
Glyphicons:
Font Awesome:
Copy
<div id="upload-demo-5" class="up-fa" data-upload-url="/upload" data-upload-delete-url="/delete"></div>
Glyphicons:
Copy
<div id="upload-demo-6" class="up-glyphicons" data-upload-url="/upload" data-upload-delete-url="/delete"></div>
Copy
var div = document.getElementById("upload-demo-5");
new UploadJs(div);

var div = document.getElementById("upload-demo-6");
new UploadJs(div);

Styling It is possible to style the stuffing out of UploadJs, here are some examples of what is possible.

In this example, the add action is fixed to the right side, the file items are circular as is the progress bar and the default colour has been changed to a dark red.
Copy
<div id="upload-demo-7" class="demo7" data-upload-url="/upload" data-upload-delete-url="/delete">
    <img src="existing-img-1.jpg" data-upload-image-id="1" />
</div>
Copy
new UploadJs(document.getElementById("upload-demo-7"), {"http": http}).on("upload.progress", function(e) {
    $(this).find(".progress").removeClass("p0 p10 p20 p30 p40 p50 p60 p70 p80 p90 p100").addClass("p" + (Math.floor(e.progress / 10) * 10));
}).on("upload.done upload.failed", function() {
    $(this).find(".progress").addClass("done");
})
Copy
.uploadjs.demo7 {
   min-height: 100px;
   position: relative;
}

.uploadjs.demo7 .item {
   border: 1px solid rgba(0, 0, 0, 0.5);
}

.uploadjs.demo7 .item.new {
   width: 40px;
   height: 40px;
   border-radius: 40px;
   position: absolute;
   right: 0px;
   top: 0px;
   background-color: transparent;
   border: 1px solid #454545;
}

.uploadjs.demo7 .item.new:hover .icon, .uploadjs.demo7 .item .action:hover, .uploadjs.demo7 .item .icon {
   color: #C40000;
}

.uploadjs.demo7 .item .icon.done, .uploadjs.demo7 .item .icon.error {
   color: #FFFFFF;
}

.uploadjs.demo7 .spinner {
   border: 2px solid #C40000;
   border-right-color: transparent;
}

.uploadjs.demo7 .item.new .icon {
   color: #454545;
}

.uploadjs.demo7 .item, .uploadjs.demo7 .item img {
   border-radius: 100%;
}

.uploadjs.demo7 .item .actions {
   text-align: center;
}

.uploadjs.demo7 .progress {
   border-radius: 100px;
   border: none;
   transform: translateX(0%) !important;
   clip: rect(0px, 100px, 100px, 50px);
   opacity: 1;
   transition: opacity 0.5s;
}

.uploadjs.demo7 .progress.done {
   opacity: 0;
}

.uploadjs.demo7 .progress::before, .uploadjs.demo7 .progress::after {
   content: ".";
   color: transparent;
   position: absolute;
   width: 100%;
   height: 100%;
   border: 2px solid #C40000;
   border-radius: 100%;
   clip: rect(0px, 50px, 100px, 0px);
   transition: transform 0.2s;
}

.uploadjs.demo7 .progress.p10::before {
   transform: rotate(36deg) !important;
}

.uploadjs.demo7 .progress.p20::before {
   transform: rotate(72deg) !important;
}

.uploadjs.demo7 .progress.p30::before {
   transform: rotate(108deg) !important;
}

.uploadjs.demo7 .progress.p40::before {
   transform: rotate(144deg) !important;
}

.uploadjs.demo7 .progress.p50::before,
.uploadjs.demo7 .progress.p60::before,
.uploadjs.demo7 .progress.p70::before,
.uploadjs.demo7 .progress.p80::before,
.uploadjs.demo7 .progress.p90::before,
.uploadjs.demo7 .progress.p100::before, 
.uploadjs.demo7 .progress.p50::after {
   transform: rotate(180deg) !important;
}

.uploadjs.demo7 .progress.p60,
.uploadjs.demo7 .progress.p70,
.uploadjs.demo7 .progress.p80,
.uploadjs.demo7 .progress.p90,
.uploadjs.demo7 .progress.p100 {
   clip: auto;
}

.uploadjs.demo7 .progress.p60::after {
   transform: rotate(216deg) !important;
}

.uploadjs.demo7 .progress.p70::after {
   transform: rotate(252deg) !important;
}

.uploadjs.demo7 .progress.p80::after {
   transform: rotate(288deg) !important;
}

.uploadjs.demo7 .progress.p90::after {
   transform: rotate(324deg) !important;
}

.uploadjs.demo7 .progress.p100::after {
   transform: rotate(360deg) !important;
}
In this example, the file items sizes have been increased and the add action styled to be a bottom floating bar.
Copy
<div id="upload-demo-8" class="demo8" data-upload-url="/upload" data-upload-delete-url="/delete">
    <img src="existing-img-1.jpg" data-upload-image-id="1" />
</div>
Copy
var div = document.getElementById("upload-demo-8");
new UploadJs(div);
Copy
.uploadjs.demo8 .item {
   width: 200px;
   height: 200px;
   vertical-align: middle;
   border-radius: 2px;
}

.uploadjs.demo8 .item.removed {
   width: 0%;
}

.uploadjs.demo8 .item.new {
   display: block;
   width: 100%;
   height: 30px;
}

Install

Download The latest release of Upload.js and add it to your project

<head>
   <link rel="stylesheet" href="path/to/css/uploadjs.css" />
</head>
<body>
   ...
   <script src="path/to/js/uploadjs.js"></script>
</body>

or

Install via the Bower package manager and add it to your project

bower install uploadjs
<head>
   <link rel="stylesheet" href="bower_components/uploadjs/dist/uploadjs.css" />
</head>
<body>
   ...
   <script src="bower_components/uploadjs/dist/uploadjs.js"></script>
</body>

Dependencies

None, zero, zilch, zip, nadda

This project is designed to be standalone. We don't force your project to have to include any other third party libraries.


Browser Support

Any browser that supports HTML5, XMLHttpRequest advanced features and File/FileReader API.

  • Chrome (28+)
  • Firefox (38+)
  • IE (10+)
  • Safari (6.0.2+)

Usage

Pretty simple really add a div to your page, find it in your script and call the UploadJs plugin.

html

<div id="my-uploadjs"></div>

javascript

var myDiv = document.getElementById("my-uploadjs")
new UploadJs(myDiv)

Initial Images

It is possible to show initial images in the widget that may previously exist. Simply include them as img tags within the div. If you are enabling deletable each img tag must include the HTML data attribute data-upload-image-id=<id> where <id> is a unique identifier for the file that will be set as the deletion parameter to the deletion URL.

<div id="my-uploadjs"></div>
   <img src="my-img-1.jpg" data-upload-image-id="1" />
   <img src="my-img-2.jpg" data-upload-image-id="2" />
</div>

Options

UploadJs is configurable in it's behaviour. All options are configurable via the javascript options, and many others as HTML data attributes. You can use a combination of the two where applicable.

Via javascipt

var options = {
   upload: {
      url: "/upload"
   },
   delete: {
      url: "/delete"
   }
}
new UploadJs(myDiv, options)

Via html data attributes

<div id="my-uploadjs" data-upload-url="/upload" data-upload-delete-url="/delete" />

Available Options

Name Option Description
Upload Url
upload: { url: <string> }
or
data-upload-url="<string>"
The URL that is called when uploading a file. The url must return JSON with success: true if the upload was successful and with uploadImageId: <id> where <id> is a unique identifier for the file that will then get called to the deletion URL. If uploadImageId is not returned the uploaded file will not be deletable from the widget.
Upload Parameter
upload: { param: <string> }
or
data-upload-param="<string>"
Default: 'file'

The name of the parameter that each file is set as in the upload request.
Deletion Url
delete: { url: <string> }
or
data-upload-delete-url="<string>"
The URL that is called when deleting a file. The url must return JSON with success: true if the deletion was successful.
Deletion Parameter
delete: { param: <string> }
or
data-upload-delete-param="<string>"
Default: 'file'

The name of the parameter set with the file id that is set on the deletion request.
Max
max: <int>
or
data-upload-max="<int>"
Default: infinite

The maximum number of files that are allowed to exist in the widget.
Deletable
deletable: <boolean>
or
data-upload-deletable="<boolean>"
Default: true

Indicates whether or not files are deletable. If true the delete button will appear for each file, when clicked the deletion url is called.
Allowed Types
allowed_types: []
or
data-upload-allowed-types="<string>[,<string>[,...]]"
Default: ["images"]

<array> or commor (,) separated <string> of allowed file MIME content types e.g. image/png, image/jpg. You can use the predefined type key images which includes ["image/jpg", "image/jpeg", "image/png", "image/gif"] e.g. allowed_types: ["images"].

Callback

When defining the options via the javascript API, option values can be defined using a function. There is an optional done callback that can be passed to the options function that should be called, passing the option value, when the option value has been loaded. If the done callback is not defined as a function parameter then the option value should be returned.

Option defined as function without callback

var uploadUrl = ...
var options = {
    upload: {
       url: function() {
          return uploadUrl;
       }
    }
}

Option defined as function with callback

var uploadUrl = ...
var options = {
    upload: {
       url: function(done) {
          done(uploadUrl);
       }
    }
}

Methods

Methods available on UploadJs and what they are good for

Method Description Event Object Usage
on(<string>, <function>) Adds a listener to UploadJs that will trigger the passed function for the event. Available events are:

  • upload.added - A new file upload has been added to the queue for upload
  • upload.started - The file upload has been taken from the queue and actual upload has stared
  • upload.progress - Fired with with the progress of the upload
  • upload.done - The upload has successfully completed with success from the server
  • upload.fail - The upload of the file failed
  • delete.added - An existing file has been added to the queue for deletion
  • delete.started - The file deletion has been taken from the queue and the request to server is being made
  • delete.done - The file was successfully deleted
  • delete.failed - The file deletion failed
The event object is passed to the handler function. It contains the following field:

  • file - field present for upload.* events, a reference to the file object.
  • id - field present for delete.* events, the file id
  • progress - int field 0-100 present for upload.progress event
var uploadJs = new UploadJs(...);
uploadJs.on("upload.success", function(e) { ... });

Styling

By default the icons used in UploadJs are unicode symbol characters

✓ ⇡ ✘ !

These can be changed to make the widget look a little nicer by using icons from either font-awesome or glyphicons. Simply add the appropriate css class to the div element. Checkout the demo to see these in action.

font awesome

<div id="my-uploadjs" class="up-fa"></div>

glyphicons

<div id="my-uploadjs" class="up-glyphicons"></div>

Issues and Contributing

If you have found a bug or would like a new feature added to UploadJs or you would just like to contribute then please read the Contributing read me before anything else.