├── .gitignore ├── Gruntfile.js ├── LICENSE ├── README.md ├── jquery-fileupload.js ├── jquery-fileupload.min.js └── package.json /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | 3 | # Node Files 4 | /node_modules/ 5 | npm-debug.log 6 | bower_components -------------------------------------------------------------------------------- /Gruntfile.js: -------------------------------------------------------------------------------- 1 | module.exports = function(grunt) 2 | { 3 | // Project configuration. 4 | grunt.initConfig({ 5 | pkg: grunt.file.readJSON('package.json'), 6 | uglify: { 7 | options: { 8 | banner: '/*! <%= pkg.name %> <%= grunt.template.today("yyyy-mm-dd") %> */\n' 9 | }, 10 | build: { 11 | src: 'jquery-fileupload.js', 12 | dest: 'jquery-fileupload.min.js' 13 | } 14 | }, 15 | jshint: { 16 | files: ['gruntfile.js', 'jquery-fileupload.js'], 17 | options: { 18 | globals: { 19 | jQuery: true, 20 | console: true, 21 | module: true 22 | } 23 | } 24 | }, 25 | watch: { 26 | scripts: { 27 | files: ['jquery-fileupload.js'], 28 | tasks: ['build'] 29 | } 30 | } 31 | }); 32 | 33 | grunt.loadNpmTasks('grunt-contrib-uglify'); 34 | grunt.loadNpmTasks('grunt-contrib-jshint'); 35 | grunt.loadNpmTasks('grunt-contrib-watch'); 36 | 37 | grunt.registerTask('default', 'build'); 38 | grunt.registerTask('build', ['jshint', 'uglify']); 39 | }; -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2013 Abban Dunne 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | jQuery-Ajax-File-Upload 2 | ======================= 3 | 4 | Plugin to add support for file uploads using jQuery $.ajax() 5 | 6 | ##What is this? 7 | All this plugin does is: 8 | 9 | 1. Grabs the files from file fields on change events and adds the data to an array. 10 | 2. On form submit it does a pre-ajax call to the back-end with the file post data. 11 | 3. After uploading, information about those files is passed back and appended to a normal $.ajax() call. 12 | 13 | ## Usage 14 | It's easy enough to use, just include it on your page and attach it to your form with: 15 | 16 | $('#myform').fileUpload(); 17 | 18 | You can pass the following parameters to it: 19 | 20 | $('#myform').fileUpload({ 21 | uploadData : { 'extra_data' : 'blah' }, // Append POST data to the upload 22 | submitData : { 'moar_extra_data' : 'blah' }, // Append POST data to the form submit 23 | uploadOptions : { dataType : 'json' }, // Customise the parameters passed to the $.ajax() call on uploads. You can use any of the normal $.ajax() params 24 | submitOptions : { dataType : 'json' }, // Customise the parameters passed to the $.ajax() call on the form submit. You can use any of the normal $.ajax() params 25 | before : function(){}, // Run stuff before the upload happens 26 | beforeSubmit : function(uploadData){ console.log(uploadData); return true; }, // access the data returned by the upload return false to stop the submit ajax call 27 | success : function(data, textStatus, jqXHR){ console.log(data); }, // Callback for the submit success ajax call 28 | error : function(jqXHR, textStatus, errorThrown){ console.log(jqXHR); }, // Callback if an error happens with your upload call or the submit call 29 | complete : function(jqXHR, textStatus){ console.log(jqXHR); } // Callback on completion 30 | }); 31 | 32 | -------------------------------------------------------------------------------- /jquery-fileupload.js: -------------------------------------------------------------------------------- 1 | /** 2 | * fileUpload 3 | * http://abandon.ie 4 | * 5 | * Plugin to add file uploads to jQuery ajax form submit 6 | * 7 | * November 2013 8 | * 9 | * @version 0.9 10 | * @author Abban Dunne http://abandon.ie 11 | * @license MIT 12 | * 13 | */ 14 | ;(function($, window, document, undefined) 15 | { 16 | // Create the defaults once 17 | var pluginName = "fileUpload", 18 | defaults = { 19 | uploadData : {}, 20 | submitData : {}, 21 | uploadOptions : {}, 22 | submitOptions : {}, 23 | before : function(){}, 24 | beforeSubmit : function(){ return true; }, 25 | success : function(){}, 26 | error : function(){}, 27 | complete : function(){} 28 | }; 29 | 30 | // The actual plugin constructor 31 | function Plugin(element, options) 32 | { 33 | this.element = element; 34 | this.$form = $(element); 35 | this.$uploaders = $('input[type=file]', this.element); 36 | this.files = {}; 37 | this.settings = $.extend({}, defaults, options); 38 | this._defaults = defaults; 39 | this._name = pluginName; 40 | this.init(); 41 | } 42 | 43 | Plugin.prototype = 44 | { 45 | /** 46 | * Initialize the plugin 47 | * 48 | * @return void 49 | */ 50 | init: function() 51 | { 52 | this.$uploaders.on('change', { context : this }, this.processFiles); 53 | this.$form.on('submit', { context : this }, this.uploadFiles); 54 | }, 55 | 56 | 57 | 58 | /** 59 | * Process files after they are added 60 | * 61 | * @param jQuery event 62 | * @return void 63 | */ 64 | processFiles: function(event) 65 | { 66 | var self = event.data.context; 67 | self.files[$(event.target).attr('name')] = event.target.files; 68 | }, 69 | 70 | 71 | 72 | /** 73 | * Handles the file uploads 74 | * 75 | * @param jQuery event 76 | * @return void 77 | */ 78 | uploadFiles: function(event) 79 | { 80 | event.stopPropagation(); // Stop stuff happening 81 | event.preventDefault(); // Totally stop stuff happening 82 | 83 | var self = event.data.context; 84 | 85 | // Run the before callback 86 | self.settings.before(); 87 | 88 | // Declare a form data object 89 | var data = new FormData(); 90 | data.append('file_upload_incoming', '1'); 91 | 92 | // Add the files 93 | $.each(self.files, function(key, field) 94 | { 95 | $.each(field, function(key, value) 96 | { 97 | data.append(key, value); 98 | }); 99 | }); 100 | 101 | // If there is uploadData passed append it 102 | $.each(self.settings.uploadData, function(key, value) 103 | { 104 | data.append(key, value); 105 | }); 106 | 107 | // Perform Ajax call 108 | $.ajax($.extend({}, { 109 | url: self.$form.attr('action'), 110 | type: 'POST', 111 | data: data, 112 | cache: false, 113 | dataType: 'json', 114 | processData: false, // Don't process the files, we're using FormData 115 | contentType: false, // Set content type to false as jQuery will tell the server its a query string request 116 | success: function(data, textStatus, jqXHR){ self.processSubmit(event, data); }, 117 | error: function(jqXHR, textStatus, errorThrown){ self.settings.error(jqXHR, textStatus, errorThrown); } 118 | }, self.settings.uploadOptions)); 119 | }, 120 | 121 | 122 | 123 | /** 124 | * Submits form data with files 125 | * 126 | * @param jQuery event 127 | * @param object 128 | * @return void 129 | */ 130 | processSubmit: function(event, uploadData) 131 | { 132 | var self = event.data.context; 133 | 134 | // Run the beforeSubmit callback 135 | if(!self.settings.beforeSubmit(uploadData)) return; 136 | 137 | // Serialize the form data 138 | var data = self.$form.serializeArray(); 139 | 140 | // Loop through the returned array from the server and add it to the new POST 141 | $.each(uploadData, function(key, value) 142 | { 143 | data.push({ 144 | 'name' : key, 145 | 'value' : value 146 | }); 147 | }); 148 | 149 | // If there is uploadData passed append it 150 | $.each(self.settings.submitData, function(key, value) 151 | { 152 | data.push({ 153 | 'name' : key, 154 | 'value' : value 155 | }); 156 | }); 157 | 158 | $.ajax($.extend({}, { 159 | url: self.$form.attr('action'), 160 | type: 'POST', 161 | data: data, 162 | cache: false, 163 | dataType: 'json', 164 | success: function(data, textStatus, jqXHR){ self.settings.success(data, textStatus, jqXHR); }, 165 | error: function(jqXHR, textStatus, errorThrown){ self.settings.error(jqXHR, textStatus, errorThrown); }, 166 | complete: function(jqXHR, textStatus){ self.settings.complete(jqXHR, textStatus); } 167 | }, self.settings.submitOptions)); 168 | } 169 | }; 170 | 171 | $.fn[pluginName] = function(options) 172 | { 173 | return this.each(function() 174 | { 175 | if(!$.data(this, "plugin_" + pluginName)) 176 | { 177 | $.data(this, "plugin_" + pluginName, new Plugin(this, options)); 178 | } 179 | }); 180 | }; 181 | 182 | })(jQuery, window, document); -------------------------------------------------------------------------------- /jquery-fileupload.min.js: -------------------------------------------------------------------------------- 1 | /*! jQuery-Ajax-File-Upload 2013-11-20 */ 2 | !function(a){function b(b,e){this.element=b,this.$form=a(b),this.$uploaders=a("input[type=file]",this.element),this.files={},this.settings=a.extend({},d,e),this._defaults=d,this._name=c,this.init()}var c="fileUpload",d={uploadData:{},submitData:{},uploadOptions:{},submitOptions:{},before:function(){},beforeSubmit:function(){return!0},success:function(){},error:function(){},complete:function(){}};b.prototype={init:function(){this.$uploaders.on("change",{context:this},this.processFiles),this.$form.on("submit",{context:this},this.uploadFiles)},processFiles:function(b){var c=b.data.context;c.files[a(b.target).attr("name")]=b.target.files},uploadFiles:function(b){b.stopPropagation(),b.preventDefault();var c=b.data.context;c.settings.before();var d=new FormData;d.append("file_upload_incoming","1"),a.each(c.files,function(b,c){a.each(c,function(a,b){d.append(a,b)})}),a.each(c.settings.uploadData,function(a,b){d.append(a,b)}),a.ajax(a.extend({},{url:c.$form.attr("action"),type:"POST",data:d,cache:!1,dataType:"json",processData:!1,contentType:!1,success:function(a){c.processSubmit(b,a)},error:function(a,b,d){c.settings.error(a,b,d)}},c.settings.uploadOptions))},processSubmit:function(b,c){var d=b.data.context;if(d.settings.beforeSubmit(c)){var e=d.$form.serializeArray();a.each(c,function(a,b){e.push({name:a,value:b})}),a.each(d.settings.submitData,function(a,b){e.push({name:a,value:b})}),a.ajax(a.extend({},{url:d.$form.attr("action"),type:"POST",data:e,cache:!1,dataType:"json",success:function(a,b,c){d.settings.success(a,b,c)},error:function(a,b,c){d.settings.error(a,b,c)},complete:function(a,b){d.settings.complete(a,b)}},d.settings.submitOptions))}}},a.fn[c]=function(d){return this.each(function(){a.data(this,"plugin_"+c)||a.data(this,"plugin_"+c,new b(this,d))})}}(jQuery,window,document); -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jQuery-Ajax-File-Upload", 3 | "version": "0.1.0", 4 | "devDependencies": { 5 | "grunt": "~0.4.1", 6 | "grunt-contrib-jshint": "~0.7.2", 7 | "grunt-contrib-uglify": "~0.2.7", 8 | "grunt-contrib-watch": "~0.2.0" 9 | } 10 | } 11 | --------------------------------------------------------------------------------