Skip to content

Instantly share code, notes, and snippets.

@mindscratch
Created February 9, 2012 16:42
Show Gist options
  • Select an option

  • Save mindscratch/1780998 to your computer and use it in GitHub Desktop.

Select an option

Save mindscratch/1780998 to your computer and use it in GitHub Desktop.
JavaScriptMVC File Upload
$('#somediv-with-upload-button').uploader({
action: '/some/where',
succses: this.callback('onUploadSuccess'),
error: this.callback('onUploadError'),
click: this.callback('onUploadClick'),
params: {
tags: ['foo', 'bar', 'baz']
});
onUploadClick: function(buttonEl, event) {
var $form = $('somediv-with-upload-button').find('form');
// TODO perform validation here maybe
return true; // or false if validation failed
},
onUploadSuccess: function() {
// TODO clear form input
// hide validation errors if any existed
},
onUploadError: function(errMessage) {
//TODO show error message
}
steal('jquery/controller',
'jquery/view/ejs',
'jquery/controller/view',
'jquery/dom/dimensions')
.then('./views/init.ejs', './upload.css')
.then(function($){
/**
* @class Jupiter.UI.Upload
* Creates an upload button that uploads right away.
*
* Example:
*
* $('#upload').jupiter_ui_upload({
* success : function(data, element){ ... }
* error : function(errorData, element) { ... }
* })
*/
$.Controller("Jupiter.UI.Upload",
{
defaults :
{
success : null,
error : null,
click: null,
started: null,
action: '',
method: 'POST',
enctype: 'multipart/form-data',
params: null
},
targetCount: 0
},{
'#upload-btn click': function(buttonEl, event) {
event.preventDefault();
var result = this.options.click && this.options.click(buttonEl, event);
if (!result) {
return;
}
var $buttonEl = $(buttonEl);
// TODO disable buttons, show 'disable' button text
if (this.startUpload() === false) {
//TODO enable buttons
}
}
/**
* Init called by base JMVC controller.
*/
init : function()
{
this.element.addClass('upload-form');
this.element.append(this.view('//mj/ui/upload/views/init.ejs'));
},
/**
* Upload input file changed.
*/
"input[type=file] change" : function()
{
if (!$.browser.msie) {
this.startUpload();
}
},
/**
* Hack for IE not firing event until blur.
*/
"input[type=file] click" : function()
{
if(this.element.hasClass('disabled')){
return false;
}
if ($.browser.msie) {
setTimeout(this.callback('startUpload'), 0);
}
},
/**
* Submits upload to server.
*/
startUpload : function()
{
this.options.started && this.options.started();
if(typeof this.targetCount != 'number'){
this.targetCount = 0;
}
var id = "upload_" + this.targetCount++,
form = this.find('form'),
val = this.find('input[type=file]').val(),
prettyName = val.replace(/^.*\\/, '');
if(!val || val == ""){
return false;
}
//- Set form values
form.attr('action', this.options.action);
form.attr('method', this.options.method);
form.attr('enctype', this.options.enctype);
//- set params
if(this.options.params){
for(var val in this.options.params){
var cur = form.find('#' + val);
if(cur.size() == 0){
form.append("<input type='hidden' name='" + val + "' id='" + val + "' value='" + this.options.params[val] + "'/>")
} else {
cur.val(this.options.params[val])
}
}
}
var iframe = $("<iframe style='display:none'/>")
.attr('id',id )
.attr('name',id)
.appendTo(document.body)
.bind('load', this.callback('uploaded', id, this.options.action));
form.attr("target", id).get(0).submit();
},
/**
* File uploaded callback.
* @param {Object} id
* @param {Object} action
*/
uploaded : function(id, action)
{
var $form = this.find('form'),
form = $form[0],
frame = $('#' + id)[0],
response = null;
// TODO enable buttons
try {
response = frame.contentWindow.document.body.innerHTML;
var data = $.parseJSON($(response).text());
if(data){
this.options.success && this.options.success(data);
}else{
this.options.error && this.options.error(frame.contentWindow.error);
}
//- reset this for chrome not firing triggered since value is the same.
this.find('input[type=file]').val('');
catch(e) {
//TODO log error
}
// remove iFrame but wrap it in a timer, otherwise the load event doesn't seem to finish
// properly. Everything actually worked fine but w/o the timer Firefox would stil show it's loading
// indicator (spinning circle).
setTimeout(function() {
$(frame).remove();
}, 100);
}
})
});
<form>
<input type="file" name="contents">
</form>
.upload-form
{
overflow:hidden;
position:relative;
}
.upload-form input
{
cursor:pointer;
position: absolute;
height:56px;
top: 0;
right: 0;
border: solid transparent;
opacity: 0;
filter: alpha(opacity=0);
-o-transform: translate(250px,-50px) scale(1);
-moz-transform: translate(-300px,0) scale(4);
bottom:0;
}
@mindscratch
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment