/* --------------------------------------------------------------
ajax_file_upload.js 2016-02-11
Gambio GmbH
http://www.gambio.de
Copyright (c) 2016 Gambio GmbH
Released under the GNU General Public License (Version 2)
[http://www.gnu.org/licenses/gpl-2.0.html]
--------------------------------------------------------------
*/
/**
* ## AJAX File Upload Extension
*
* This extension will enable an existing **input[type=file]** element to upload files through AJAX.
* The upload method can be invoked either manually by calling the "upload" function or automatically
* once the file is selected. A "validate" event is triggered before upload starts so that you can
* validate the selected file before it is uploaded and stop the procedure if needed.
*
* Currently the module supports the basic upload functionality but you can add extra logic on your own
* by following code examples in the official page of the plugin.
*
* The "auto" option is enabled by default which means that the extension will automatically trigger
* the upload operation when the user selects a file.
*
* {@link https://github.com/blueimp/jQuery-File-Upload/wiki/Basic-plugin}
*
* **Important**: If you need to support older versions of Internet Explorer you should use the automatic upload
* mode because the manual mode uses the JavaScript File API and this is supported from IE 10+.
*
* ### Options
*
* **URL | `data-ajax_upload_file-url` | String | Required**
*
* Define the upload URL that will handle the file upload.
*
* **Auto | `data-ajax_upload_file-auto` | Boolean | Optional**
*
* Define whether the upload process will be started automatically after the user selects a file.
*
* ### Events
* ```javascript
* // Add your validation rules, triggered before upload (Manual Mode - Requires JS file API support).
* $('#upload-file').on('validate', function(event, file) {});
*
* // Triggered when server responds to upload request (Manual + Auto Mode).
* $('#upload-file').on('upload', function(event, response) {});
* ```
*
* ### Methods
* ```javascript
* // Trigger the selected file validation, returns a bool value.
* $('#upload-file').validate();
*
* // Trigger the file upload, callback argument is optional.
* $('#upload-file').upload(callback);
* ```
*
* ### Example
*
* **Automatic Upload**
*
* The upload process will be triggered automatically after the user selects a file.
*
* ```html
* <!-- HTML -->
* <input id="upload-file" type="file" data-gx-extension="ajax_file_upload"
* data-ajax_file_upload-url="http://url/to/upload-script.php" />
*
* <!-- JavaScript -->
* <script>
* $('#upload-file').on('validate', function(event, file) {
* // Validation Checks (Only IE 10+) ...
* return true; // Return true for success or false for failure - will stop the upload.
* });
*
* $('#upload-file').on('upload', function(event, response) {
* // The "response" parameter contains the server's response information.
* });
* </script>
* ```
*
* **Manual Upload**
*
* The upload process needs to be triggered through JavaScript as shown in the following example.
*
*
* ```html
* <!-- HTML -->
* <input id="upload-file" type="file" data-gx-extension="ajax_file_upload"
* data-ajax_file_upload-url="http://url/to/upload-script.php"
* data-ajax_file_upload-auto="false" />
* <button id="upload-file-button">Trigger Upload</button>
*
* <!-- JavaScript -->
* <script>
* $('#upload-file-button').on('click', function() {
* $('#upload-file').upload(function(response) {
* // Callback Function (Optional)
* });
* });
* </script>
* ```
*
* @module Admin/Extensions/ajax_file_upload
* @requires jQuery-File-Upload
*/
gx.extensions.module(
'ajax_file_upload',
[
jse.source + '/vendor/blueimp-file-upload/jquery.fileupload.min.js'
],
function (data) {
'use strict';
// ------------------------------------------------------------------------
// VARIABLE DEFINITION
// ------------------------------------------------------------------------
var
/**
* Extension Reference Selector
*
* @type {object}
*/
$this = $(this),
/**
* Default Options for Extension.
*
* @type {object}
*/
defaults = {
auto: true
},
/**
* Final Extension Options
*
* @type {object}
*/
options = $.extend(true, {}, defaults, data),
/**
* Module Object
*
* @type {object}
*/
module = {};
// ------------------------------------------------------------------------
// FUNCTIONALITY
// ------------------------------------------------------------------------
/**
* Check method element type.
*
* The element that uses the extended jquery methods must be an input[type=file].
* Otherwise an exception is thrown.
*
* @param {object} $element jQuery selector for the element to be checked.
*
* @throws Exception when the element called is not a valid input[type=file].
*
* @private
*/
var _checkElementType = function ($element) {
if (!$element.is('input[type=file]')) {
throw '$.upload() method is supported only in input[type=file] elements.';
}
};
/**
* Uploads selected file to server.
*
* This method uses the JavaScript File API that is supported from IE10+. If
* you need to support older browser just enable the auto-upload option and do
* not use this method.
*
* @param callback
*/
var _upload = function (callback) {
// Trigger "validate" event for file upload element.
var file = $this.get(0).files[0];
if (!_validate(file) || !$this.trigger('validate', [file])) {
return; // Do not continue as validation checks failed.
}
// Create a new instance of the plugin and upload the selected file.
$this.fileupload({
url: options.url,
dataType: 'json'
});
$this.fileupload('send', {
files: [file]
})
.done(function (result, textStatus, jqXHR, file) {
jse.core.debug.info('AJAX File Upload Success Response:', result, textStatus);
if (typeof callback === 'function') {
callback(result);
}
})
.error(function (jqXHR, textStatus, errorThrown) {
jse.core.debug.error('AJAX File Upload Failure Response:', jqXHR, textStatus, errorThrown);
})
.complete(function (result, textStatus, jqXHR) {
$this.fileupload('destroy'); // Not necessary anymore.
});
};
/**
* Default Validation Rules
*
* This method will check for invalid filenames or exceeded file size (if necessary).
*
* @param {object} file Contains the information of the file to be uploaded.
*/
var _validate = function (file) {
// @todo Implement default file validation.
try {
// Check if a file was selected.
if (file === undefined) {
throw 'No file was selected for upload.';
}
return true;
} catch (exception) {
jse.core.debug.error(exception);
return false;
}
};
// ------------------------------------------------------------------------
// INITIALIZATION
// ------------------------------------------------------------------------
/**
* Initialize function of the extension, called by the engine.
*/
module.init = function (done) {
// Check if upload script URL was provided (required value).
if (options.url === undefined || options.url === '') {
jse.core.debug.error('Upload URL was not provided for "ajax_file_upload" extension.');
return;
}
if (options.auto === true) {
$this.fileupload({
'dataType': 'json',
'url': options.url,
done: function (event, data) {
$(this).trigger('upload', [data.result]);
}
});
} else {
// Extend jQuery object with upload method for element.
$.fn.extend({
upload: function (callback) {
_checkElementType($(this));
_upload(callback); // Trigger upload handler
},
validate: function () {
_checkElementType($(this));
return _validate(this.files[0]);
}
});
}
// Notify engine that the extension initialization is complete.
done();
};
// Return data to module engine.
return module;
});