Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Initial Commit

  • Loading branch information...
commit 5e7874eb6748dfd74f3bfa7fad783ff8d43e1ec0 0 parents
@arian authored
54 Demos/Upload.html
@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<html>
+<head>
+
+<title>Multiple Upload</title>
+<script src="https://ajax.googleapis.com/ajax/libs/mootools/1.3.2/mootools.js"></script>
+<script src="../Source/Request.File.js"></script>
+<script src="../Source/Form.MultipleFileInput.js"></script>
+<script src="../Source/Form.Upload.js"></script>
+<link href="http://fonts.googleapis.com/css?family=Ubuntu" rel="stylesheet" type="text/css" />
+<link href="styles.css" rel="stylesheet" type="text/css" />
+
+<script>
+
+window.addEvent('domready', function(){
+
+ var upload = new Form.Upload('url', {
+ onComplete: function(){
+ alert('Completed uploading the Files');
+ }
+ });
+
+ if (!upload.isModern()){
+ // Use something like
+ }
+
+});
+
+</script>
+
+</head>
+<body>
+
+<div id="wrapper">
+
+ <form method="post" action="files.php" enctype="multipart/form-data">
+ <fieldset>
+ <legend>Upload Files</legend>
+
+ <div class="formRow">
+ <label for="url" class="floated">File: </label>
+ <input type="file" id="url" name="url[]" multiple><br>
+ </div>
+
+ <div class="formRow">
+ <input type="submit" id="_submit" name="_submit" value="Upload">
+ </div>
+
+ </fieldset></form>
+
+</div>
+
+</body>
+</html>
BIN  Demos/add.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  Demos/delete.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 Demos/files.php
@@ -0,0 +1,8 @@
+<?php
+
+echo '<pre>';
+
+print_r($_FILES);
+
+print_r($_POST);
+
111 Demos/styles.css
@@ -0,0 +1,111 @@
+
+/* some general styles */
+
+body {
+ font: 0.9em 'Ubuntu', arial, sans-serif;
+}
+
+#wrapper {
+ margin: 100px auto;
+ width: 50%;
+}
+
+fieldset {
+ border: 0;
+}
+
+form {
+ border-top: 1px #545a74 solid;
+ border-bottom: 1px #545a74 solid;
+ background: #e2e5f3;
+ margin: 20px 0;
+ padding: 10px;
+}
+
+fieldset legend {
+ color: #666;
+ margin: 0;
+ font-size: 1.5em;
+ font-weight: normal;
+ padding-bottom: 20px;
+}
+
+.formRow {
+ overflow: auto;
+ border-bottom: 1px #bcbcbc solid;
+ padding: 5px 0;
+ max-width: 100%;
+}
+
+.formRow label {
+ padding: 4px;
+ margin: 0 3px 0 0;
+ border-right: 1px #bcbcbc solid;
+}
+
+
+/* Drag & Drop file uploading */
+
+.droppable {
+ border: #121a3f 1px solid;
+ border-radius: 3px;
+ background: #545A74;
+ color: white;
+ padding: 20px;
+ margin: 10px;
+ clear: both;
+ text-align: center;
+}
+
+.droppable.hover {
+ background: #121a3f;
+}
+
+.uploadList {
+ margin: 0;
+ padding: 0;
+ list-style: none;
+}
+
+.uploadItem {
+ overflow: hidden;
+ border-bottom: #BCBCBC 1px solid;
+ margin: 0 20px;
+ padding: 3px;
+}
+
+.uploadItem span {
+ overflow: hidden;
+ width: 150px;
+ float: left;
+ display: block;
+}
+
+a.addInputRow,
+a.delInputRow,
+.uploadItem a {
+ display: inline-block;
+ background: url(add.png) no-repeat;
+ height: 16px;
+ width: 16px;
+ text-indent: -999px;
+}
+
+.uploadItem a {
+ float: left;
+ display: block;
+ padding-left: 20px;
+ background-image: url(delete.png);
+}
+
+a.delInputRow {
+ background-image: url(delete.png);
+}
+
+.progress {
+ margin: 5px 0;
+ height: 15px;
+ border-radius: 3px;
+ background: #545A74;
+}
+
159 README.md
@@ -0,0 +1,159 @@
+Multiple File Upload with HTML5
+===============================
+
+Upload your files the HTML5 way, drag and drop from your computer, multiple
+files the ajaxy way!
+
+It works about the same as uploading attachments to gmail.
+
+- HTML5 Drag and Drop files from your computer
+- HTML5 multiple attribute files for selecting multiple files
+- Uploading files through XMLHttpRequest with FormData
+- Progress bar
+- Graceful degradation for IE / Opera
+
+
+How To Use
+-----------
+
+Include the JavaScript files in your page, for example with the `<script>` tag,
+or with a Script Loader with an extra check for `FormData` support.
+
+When using the last option it'll look something like:
+
+ #JS
+ if ('FormData' in window){
+ // Load Form.MultipleFileInput.js
+ // Load Request.File.js
+ } else {
+ // Load IframeFormRequest
+ // e.g. http://mootools.net/forge/p/iframeformrequest
+ }
+
+If you're not using a Script Loader, just include MooTools and all three files:
+
+ #HTML
+ <script src="https://ajax.googleapis.com/ajax/libs/mootools/1.3.2/mootools.js"></script>
+ <script src="../Source/Request.File.js"></script>
+ <script src="../Source/Form.MultipleFileInput.js"></script>
+ <script src="../Source/Form.Upload.js"></script>
+
+To get the magic running just initiate the Form.Upload class:
+
+ #JS
+ new Form.Upload('url');
+
+This is for the html structure like
+
+ #HTML
+ <form method="post" action="files.php" enctype="multipart/form-data">
+ <fieldset>
+ <legend>Upload Files</legend>
+
+ <div class="formRow">
+ <label for="url" class="floated">File: </label>
+ <input type="file" id="url" name="url[]" multiple><br>
+ </div>
+
+ <div class="formRow">
+ <input type="submit" name="upload" value="Upload">
+ </div>
+
+ </fieldset></form>
+
+### Events
+
+The `Form.Upload` class has only one event: `onComplete`. This is only used
+in the HTML5 uploader
+
+### Graceful Degradation
+
+Note that in the HTML the input is wrapped in a `div.formRow` element. This
+is for the graceful degradation in older browsers. The Form.Upload class will
+clone the first parent that maches `.formRow` of the `input#url` element. Then
+it will append the clones after that `div.formRow` element.
+
+By default it will just upload the files and go to the page given in the action
+attribute, like any other form post. With the `isModern()` method you could
+check whether it's using the HTML5 possibilities or the legacy upload.
+
+**Example**
+
+ #JS
+
+ var upload = new Form.Upload('url', {
+ onComplete: function(){
+ alert('Completed uploading the Files');
+ }
+ });
+
+ if (!upload.isModern()){
+ // using iFrameFormRequest from the forge to upload the files
+ // in an IFrame.
+ new iFrameFormRequest('myForm', {
+ onComplete: function(response){
+ alert('Completed uploading the files');
+ }
+ });
+ }
+
+### Using the files separately
+
+The Form.Upload Class is just a useful class to use when you quickly want to
+build the upload form. However the `Form.MultipleFileInput` and `File.Request`
+classes can be used separately too!
+
+#### Form.MultipleFileInput
+
+This is a class that transforms a simple `input[type="file"]` into a multiple
+file input field with even drag and drop!
+
+Checkout the source for all options and events. That's not very spectacular.
+
+#### Request.File
+
+This is a class that extends Request and brings file uploading to Request.
+Some credits should go to fellow MooTools Developer Djamil Legato for proving
+this class.
+
+In this version it is a very stripped down version and not all Request options
+might work. In 95% of the cases you don't really need them though, so it doesn't
+matter really.
+
+#### Combining Form.MultipleFileInput and Request.File
+
+When the user has selected all the files, they can be uploaded.
+To bridge those to classes, usually Form.Upload can be used.
+
+However if you want more control, the following can be done:
+
+ #JS
+ // the input element, the list (ul) and the drop zone element.
+ var input, list, drop;
+ // Form.MultipleFileInput instance
+ var inputFiles = new Form.MultipleFileInput(input, list, drop, {
+ onDragenter: drop.addClass.pass('hover', drop),
+ onDragleave: drop.removeClass.pass('hover', drop),
+ onDrop: drop.removeClass.pass('hover', drop)
+ });
+
+ // Request instance;
+ var request = new Request.File({
+ url: 'files.php'
+ // onSuccess
+ // onProgress
+ });
+
+ myForm.addEvent('submit', function(event){
+ event.preventDefault();
+ inputFiles.getFiles().each(function(file){
+ request.append('url[]' , file);
+ });
+ request.send();
+ });
+
+In the last loop, we loop over the [File](http://www.w3.org/TR/FileAPI/)
+instances and we append them to the request:
+
+ request.append((string) fieldname, (File) file);
+
116 Source/Form.MultipleFileInput.js
@@ -0,0 +1,116 @@
+/*
+---
+
+name: Form.MultipleFileInput
+description: Create a list of files that has to be uploaded
+license: MIT-style license.
+requires: [Element.Event, Class, Options, Events]
+provides: Form.MultipleFileInput
+
+...
+*/
+
+
+Object.append(Element.NativeEvents, {
+ dragenter: 2, dragleave: 2, dragover: 2, dragend: 2, drop: 2
+});
+
+if (!this.Form) this.Form = {};
+
+Form.MultipleFileInput = new Class({
+
+ Implements: [Options, Events],
+
+ options: {
+ itemClass: 'uploadItem'/*,
+ onAdd: function(file){},
+ onRemove: function(file){},
+ onEmpty: function(){},
+ onDragenter: function(event){},
+ onDragleave: function(event){},
+ onDragover: function(event){},
+ onDrop: function(event){}*/
+ },
+
+ _files: [],
+
+ initialize: function(input, list, drop, options){
+ input = this.element = document.id(input);
+ list = this.list = document.id(list);
+ drop = this.drop = document.id(drop);
+
+ this.setOptions(options);
+
+ var name = input.get('name');
+ if (name.slice(-2) != '[]') input.set('name', name + '[]');
+ input.set('multiple', true);
+
+ this.inputEvents = {
+ change: function(){
+ Array.each(input.files, this.add, this);
+ }.bind(this)
+ };
+
+ this.dragEvents = drop && (typeof document.body.draggable != 'undefined') ? {
+ dragenter: this.fireEvent.bind(this, 'dragenter'),
+ dragleave: this.fireEvent.bind(this, 'dragleave'),
+ dragend: this.fireEvent.bind(this, 'dragend'),
+ dragover: function(event){
+ event.preventDefault();
+ this.fireEvent('dragover', event);
+ }.bind(this),
+ drop: function(event){
+ event.preventDefault();
+ var dataTransfer = event.event.dataTransfer;
+ if (dataTransfer) Array.each(dataTransfer.files, this.add, this);
+ this.fireEvent('drop', event);
+ }.bind(this)
+ } : null;
+
+ this.attach();
+ },
+
+ attach: function(){
+ this.element.addEvents(this.inputEvents);
+ if (this.dragEvents) this.drop.addEvents(this.dragEvents);
+ },
+
+ detach: function(){
+ this.input.removeEvents(this.inputEvents);
+ if (this.dragEvents) this.drop.removeEvents(this.dragEvents);
+ },
+
+ add: function(file){
+ this._files.push(file);
+ var self = this;
+ new Element('li', {
+ 'class': this.options.itemClass
+ }).grab(new Element('span', {
+ text: file.name
+ })).grab(new Element('a', {
+ text: 'x',
+ href: '#',
+ events: {click: function(e){
+ e.preventDefault();
+ self.remove(file);
+ }}
+ })).inject(this.list);
+ this.fireEvent('add', file);
+ return this;
+ },
+
+ remove: function(file){
+ var index = this._files.indexOf(file);
+ if (index == -1) return this;
+ this._files.splice(index, 1);
+ this.list.childNodes[index].destroy();
+ this.fireEvent('remove', file);
+ if (!this._files.length) this.fireEvent('empty');
+ return this;
+ },
+
+ getFiles: function(){
+ return this._files;
+ }
+
+});
116 Source/Form.Upload.js
@@ -0,0 +1,116 @@
+/*
+---
+
+name: Form.Upload
+description: Create a multiple file upload form
+license: MIT-style license.
+requires: [Form.MultipleFileInput, Request.File]
+provides: Form.Upload
+
+...
+*/
+
+if (!this.Form) this.Form = {};
+
+Form.Upload = new Class({
+
+ Implements: [Options, Events],
+
+ options: {
+ dropMsg: 'Please drop your files here',
+ onComplete: function(){
+ // reload
+ window.location.href = window.location.href;
+ }
+ },
+
+ initialize: function(input, options){
+ input = this.input = document.id(input);
+
+ this.setOptions(options);
+
+ // Our modern file upload requires FormData to upload
+ if ('FormData' in window) this.modernUpload(input);
+ else this.legacyUpload(input);
+ },
+
+ modernUpload: function(input){
+
+ this.modern = true;
+
+ var form = input.getParent('form');
+ if (!form) return;
+
+ var self = this,
+
+ drop = new Element('div.droppable', {
+ text: this.options.dropMsg
+ }).inject(input, 'after'),
+
+ list = new Element('ul.uploadList').inject(drop, 'after'),
+
+ progress = new Element('div.progress')
+ .setStyle('display', 'none').inject(list, 'after'),
+
+ inputFiles = new Form.MultipleFileInput(input, list, drop, {
+ onDragenter: drop.addClass.pass('hover', drop),
+ onDragleave: drop.removeClass.pass('hover', drop),
+ onDrop: drop.removeClass.pass('hover', drop)
+ }),
+
+ uploadReq = new Request.File({
+ url: form.get('action'),
+ onRequest: progress.setStyles.pass({display: 'block', width: 0}, progress),
+ onProgress: function(event){
+ var loaded = event.loaded, total = event.total;
+ progress.setStyle('width', parseInt(loaded / total * 100, 10).limit(0, 100) + '%');
+ },
+ onComplete: function(){
+ progress.setStyle('width', '100%');
+ self.fireEvent('complete', arguments);
+ }
+ }),
+
+ inputname = input.get('name');
+
+ form.addEvent('submit', function(event){
+ event.preventDefault();
+ inputFiles.getFiles().each(function(file){
+ uploadReq.append(inputname , file);
+ });
+ uploadReq.send();
+ });
+
+ },
+
+ legacyUpload: function(input){
+
+ var row = input.getParent('.formRow');
+ rowClone = row.clone(),
+ add = function(event){
+ event.preventDefault();
+ var newRow = rowClone.clone();
+
+ newRow.getElement('input').grab(new Element('a.delInputRow', {
+ text: 'x',
+ events: {click: function(event){
+ event.preventDefault();
+ newRow.destroy();
+ }}
+ }), 'after');
+
+ newRow.inject(row, 'after');
+ };
+
+ new Element('a.addInputRow', {
+ text: '+',
+ events: {click: add}
+ }).inject(input, 'after');
+
+ },
+
+ isModern: function(){
+ return !!this.modern;
+ }
+
+});
74 Source/Request.File.js
@@ -0,0 +1,74 @@
+/*
+---
+
+name: Request.File
+description: Uploading files with FormData
+license: MIT-style license.
+requires: [Request]
+provides: Request.File
+credits: https://gist.github.com/a77b537e729aff97429c
+
+...
+*/
+
+(function(){
+
+var progressSupport = ('onprogress' in new Browser.Request);
+
+Request.File = new Class({
+
+ Extends: Request,
+
+ options: {
+ emulation: false,
+ urlEncoded: false
+ },
+
+ initialize: function(options){
+ this.xhr = new Browser.Request();
+ this.formData = new FormData();
+ this.setOptions(options);
+ this.headers = this.options.headers;
+ },
+
+ append: function(key, value){
+ this.formData.append(key, value);
+ return this.formData;
+ },
+
+ send: function(options){
+ if (!this.check(options)) return this;
+
+ this.options.isSuccess = this.options.isSuccess || this.isSuccess;
+ this.running = true;
+
+ var xhr = this.xhr;
+ if (progressSupport){
+ xhr.onloadstart = this.loadstart.bind(this);
+ xhr.onprogress = this.progress.bind(this);
+ xhr.upload.onprogress = this.progress.bind(this);
+ }
+
+ xhr.open('POST', this.options.url, true);
+ xhr.onreadystatechange = this.onStateChange.bind(this);
+
+ Object.each(this.headers, function(value, key){
+ try {
+ xhr.setRequestHeader(key, value);
+ } catch (e){
+ this.fireEvent('exception', [key, value]);
+ }
+ }, this);
+
+ this.fireEvent('request');
+ xhr.send(this.formData);
+
+ if (!this.options.async) this.onStateChange();
+ if (this.options.timeout) this.timer = this.timeout.delay(this.options.timeout, this);
+ return this;
+ }
+
+});
+
+})();
+
12 package.yml
@@ -0,0 +1,12 @@
+name: Form.Upload
+author: astolwijk
+current: 0.1
+category: utilities
+tags: [upload, html5, file, "drag and drop"]
+license: MIT
+description: HTML5 Upload for multiple files
+
+sources:
+ - "Source/Form.MultipleFileInput.js"
+ - "Source/Request.File.js"
+ - "Source/Form.Upload.js"
Please sign in to comment.
Something went wrong with that request. Please try again.