Skip to content

Instantly share code, notes, and snippets.

@joelso
Created December 11, 2011 14:48
Show Gist options
  • Save joelso/1460948 to your computer and use it in GitHub Desktop.
Save joelso/1460948 to your computer and use it in GitHub Desktop.
jquery plugin wrapper of Valums fileuploader
<!DOCTYPE html>
<html>
<head>
<style type="text/css" media="screen">
section { padding-top:20px; }
</style>
<link rel="stylesheet" href="http://twitter.github.com/bootstrap/1.4.0/bootstrap.min.css">
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js" type="text/javascript" charset="utf-8"></script>
<script src="https://raw.github.com/valums/file-uploader/master/client/fileuploader.js" type="text/javascript" charset="utf-8"></script>
<script src="jquery.ajaxupload.js" type="text/javascript" charset="utf-8"></script>
<script src="jquery.attach-btn.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript" charset="utf-8">
$(function() {
$('#ajax-upload').ajaxUpload({
url: "mock-response.html",
disableOnSubmit: false,
allowedExtensions: ["jpg", "png", "gif", "bmp"]
});
// Make use global event "uploaded"
$("#uploadedFiles").bind("uploaded",
function(e, id, filename, json) {
$(this).append("<li>" + filename + "</li>");
});
$('#attachBtn').attachBtn({ uploadUrl:"mock-response.html", deleteUrl:"mock-response.html" });
});
</script>
</head>
<body>
<div class="container">
<section>
<h1>jquery.ajaxUpload</h1>
<p>This will start a fake upload that always returns "success".</p>
<a href="#" id="ajax-upload"class="btn">Click to upload</a>
<h3>Uploaded files</h3>
<ul id="uploadedFiles">
</ul>
<hr />
<h2>jquery.attach-btn</h2>
<div id="attachBtn">
<!-- Will be populated by widget -->
</div>
</section>
</div>
</body>
</html>
/*
* Just a simple jquery plugin wrapper of Andrew Valums great plugin:
* http://github.com/valums/file-uploader
*
* Please use original script to unleash all its powers. This
* basically only works for the use-case where you have an element
* (i.e. a button or link) that should trigger opening of file dialog
* and start upload after user has choosen a file.
*
* Example:
*
* $('#upload-btn').ajaxUpload({
* url: "/upload",
* complete: function(id, filename, json) {
* console.log("Yay, uploaded file: " + filename);
* }
* });
*
* Author: Joel Soderstrom
*/
;(function($) {
$.fn.ajaxUpload = function(opts) {
var defaults = {
url: '/', // (required) URL where to upload
allowedExtensions: [], // Array of allowed file type, i.e. ["jpg", "jpeg", "gif", "png", "gif"]
disableOnProgress: true, // If upload of another file should be disabled while file is uloading
complete: function(id, fileName, json) {}, // Callback when upload has finished
progress: function(id, fileName, loaded, total) {}, // Callback on progress, i.e. show a spinner
submit: function() {} // Callback when file has been submitted
};
opts = $.extend(defaults, opts);
return this.each(function() {
var $this = $(this),
uploader = new qq.FileUploaderBasic({
button: $this[0],
action: opts.url,
allowedExtensions: opts.allowedExtensions,
onComplete: function(id, fileName, json) {
if (opts.disableOnProgress) {
$this.unbind('click');
}
// trigger global event "uploaded"
$.event.trigger("uploaded", [id, fileName, json]);
opts.complete.call(this, id, fileName, json);
},
onProgress: opts.progress,
onSubmit: function() {
if (opts.disableOnProgress) {
$this.click(function(e) {
e.preventDefault();
});
}
opts.submit.call(this);
}
});
$this.data('ajaxUpload', uploader);
});
};
})(jQuery);
/*!
*
* Usage:
*
* $('#hiddenInput').attachBtn();
*
* <input type="hidden" value="{id:1, filename:'fooo'}" id="hiddenInput" />
*
* Author: Joel Soderstrom
* @requries jquery.ajax-upload.js
*/
;(function($) {
var defaults = {
model: undefined,
deleteUrl: "/delete", // String or function that returns string with model as arg
uploadUrl: "/upload", // String or function that returns string
fileUrl: function(model){}, // Function that returns string with model as arg
uploadBtnTemplate: '<span class="btn upload">{uploadMsg}</span>',
uploadedTemplate: '<div><a href="{fileUrl}" class="filename">{filename}</a><a class="del btn small" href="{deleteUrl}">{deleteMsg}</a></div>',
loadingTemplate: '<img src="loading.gif" alt="Loading..." />',
uploadMsg: "Upload",
deleteMsg: "Delete",
deleteConfirmMsg: "Are you sure you want to delete file?"
};
function Plugin(el, opts) {
this.opts = $.extend({}, defaults, opts);
this.el = el;
// decide what state to render based on model
$.isEmptyObject(this.opts.model) ? renderEmpty.call(this) : renderUploaded.call(this);
};
/**
* Render state "empty"
*/
function renderEmpty() {
var oThis = this,
uploadUrl,
uploadBtn = $(this.opts.uploadBtnTemplate).text(this.opts.uploadMsg);
// clear any existing child els and add button to container
this.el.empty().append(uploadBtn);
// upload URL can be either a string or a function
uploadUrl = getVal(this.opts.uploadUrl);
// init ajax upload
uploadBtn.ajaxUpload({
url: uploadUrl,
submit: function() {
renderLoading.call(oThis);
},
complete: function(id, filename, json) {
oThis.opts.model = json;
renderUploaded.call(oThis, filename);
}
});
}
/**
* Render state "uploaded"
*/
function renderUploaded(filename) {
var uploadedTemplate = $(this.opts.uploadedTemplate),
fileUrl = getVal(this.opts.fileUrl, this.opts.model),
deleteUrl = getVal(this.opts.deleteUrl, this.opts.model);
uploadedTemplate
.find('.filename')
.attr('href', fileUrl)
.text(filename ? filename : this.opts.model.filename)
.end()
.find('.del')
.attr('href', deleteUrl)
.text(this.opts.deleteMsg)
.bind('click', { oThis: this }, deleteFile);
this.el.empty().append(uploadedTemplate);
}
/**
* Render state "loading"
*/
function renderLoading() {
var loading = $(this.opts.loadingTemplate);
this.el.empty().append(loading);
}
/**
* Call "delete" on server and trigger rendering
* of new view when done.
*/
function deleteFile(e) {
if(confirm(e.data.oThis.opts.deleteConfirmMsg)) {
$.ajax({
url: $(this).attr('href'),
success: function() {
renderEmpty.call(e.data.oThis);
}
});
}
return false;
}
function getVal(objOrFunc, arg) {
return isFunction(objOrFunc) ? objOrFunc(arg) : objOrFunc;
}
/**
* Helper method to see if given argument is a function.
* Based on this answer: http://stackoverflow.com/a/7356528/83592
*/
function isFunction(functionToCheck) {
return functionToCheck && {}.toString.call(functionToCheck) == '[object Function]';
}
$.fn.attachBtn = function(opts) {
return this.each(function() {
new Plugin($(this), opts);
});
};
})(jQuery);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment