1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301
| // Copyright (c) 2008 Andris Valums, http://valums.com
// Licensed under the MIT license (http://valums.com/mit-license/)
// Thanks to Loic Fontaine, Mark Feldman, Andras Popovics, Faisal for contribution
/*
Changelog:
Version 0.6 - Fixed bugs:
1. Disabling button while uploading resulted in empty upload
2. Submitting empty file input in Chrome, when user clicked cancel
*/
(function($){
// we need jQuery to run
if ( ! $) return;
$.ajax_upload = function(button, options){
// make sure it is jquery object
button = $(button);
if (button.size() != 1 ){
console.error('You passed ', button.size(),' elements to ajax_upload at once');
return false;
}
return new Ajax_upload(button, options);
};
/**
* Function generates unique id
* @return unique id
*/
var get_uid = function(){
var uid = 0;
return function(){
return uid++;
}
}();
/**
* @param button Element that will be used as file upload button
* @param option User options
*/
var Ajax_upload = function(button, options){
this.button = button;
this.wrapper = null;
this.form = null;
this.input = null;
this.iframe = null;
this.disabled = false;
this.submitting = false;
this.settings = {
// Location of the server-side upload script
action: 'upload.php',
// File upload name
name: 'userfile',
// Additional data to send
data: {},
// Fired when user selects file
// You can return false to cancel upload
onSubmit: function(file, extension) {},
// Fired when file upload is completed
onComplete: function(file, response) {},
// Fired when server returns the "success" string
onSuccess: function(file){},
// Fired when server return something else
onError: function(file, response){}
};
// Merge the users options with our defaults
$.extend(this.settings, options);
this.create_wrapper();
this.create_input();
if (/MSIE/.test(navigator.userAgent)) {
// fix ie transparent background bug
this.make_parent_opaque();
}
this.create_iframe();
}
// assigning methods to our class
Ajax_upload.prototype = {
set_data : function(data){
this.settings.data = data;
},
disable : function(){
this.disabled = true;
if ( ! this.submitting){
this.input.attr('disabled', true);
}
},
enable : function(){
this.disabled = false;
this.input.attr('disabled', false);
},
/**
* Creates wrapper for button and invisible file input
*/
create_wrapper : function(){
// Shorten names
var button = this.button, wrapper;
wrapper = this.wrapper = $('<div></div>')
.insertAfter(button)
.append(button);
// wait a bit because of FF bug
// it can't properly calculate the outerHeight
setTimeout(function(){
wrapper.css({
position: 'relative'
,display: 'block'
,overflow: 'hidden'
,height: button.outerHeight(true)
,width: button.outerWidth(true)
});
}, 1);
var self = this;
wrapper.mousemove(function(e){
// Move the input with the mouse, so the user can't misclick it
if (!self.input) {
return;
}
self.input.css({
top: e.pageY - wrapper.offset().top - 5 + 'px'
,left: e.pageX - wrapper.offset().left - 170 + 'px'
});
});
},
/**
* Creates invisible file input above the button
*/
create_input : function(){
var self = this;
this.input =
$('<input type="file" />')
.attr('name', this.settings.name)
.css({
'position' : 'absolute'
,'margin': 0
,'padding': 0
,'width': '220px'
,'heigth': '10px'
,'opacity': 0
})
.change(function(){
if ($(this).val() == ''){
// there is no file
return;
}
// we need to lock "disable" method
self.submitting = true;
// Submit form when value is changed
self.submit();
// unlock "disable" method
self.submitting = false;
})
.appendTo(this.wrapper)
// Emulate button hover effect
.hover(
function(){self.button.addClass('hover');}
,function(){self.button.removeClass('hover');}
);
if (this.disabled){
this.input.attr('disabled', true);
}
},
/**
* Creates iframe with unique name
*/
create_iframe : function(){
// unique name
// We cannot use getTime, because it sometimes return
// same value in safari :(
var name = 'iframe_au' + get_uid();
// create iframe, so we dont need to refresh page
this.iframe =
$('<iframe name="' + name + '"></iframe>')
.css('display', 'none')
.appendTo('body');
},
/**
* Upload file without refreshing the page
*/
submit : function(){
var self = this, settings = this.settings;
// get filename from input
var file = this.file_from_path(this.input.val());
// execute user event
if (settings.onSubmit.call(this, file, this.get_ext(file)) === false){
// Do not continue if user function returns false
if (self.disabled){
this.input.attr('disabled', true);
}
return;
}
this.create_form();
this.input.appendTo(this.form);
this.form.submit();
this.input.remove(); this.input = null;
this.form.remove(); this.form = null;
this.submitting = false;
// create new input
this.create_input();
var iframe = this.iframe;
iframe.load(function(){
var response = iframe.contents().find('body').html();
settings.onComplete.call(self, file, response);
if (response == 'success'){
settings.onSuccess.call(self, file);
} else {
settings.onError.call(self, file, response);
}
// clear (wait a bit because of FF2 bug)
setTimeout(function(){
iframe.remove();
}, 1);
});
// Create new iframe, so we can have multiple uploads at once
this.create_iframe();
},
/**
* Creates form, that will be submitted to iframe
*/
create_form : function(){
// enctype must be specified here
// because changing this attr on the fly is not allowed
this.form =
$('<form method="post" enctype="multipart/form-data"></form>')
.appendTo('body')
.attr({
"action" : this.settings.action
,"target" : this.iframe.attr('name')
});
// Create hidden input element for each data key
for (var i in this.settings.data){
$('<input type="hidden" />')
.appendTo(this.form)
.attr({
'name': i
,'value': this.settings.data[i]
});
}
},
file_from_path : function(file){
var i = file.lastIndexOf('\\');
if (i !== -1 ){
return file.slice(i+1);
}
return file;
},
get_ext : function(file){
var i = file.lastIndexOf('.');
if (i !== -1 ){
return file.slice(i+1);
}
return '';
},
make_parent_opaque : function(){
// ie transparent background bug
this.button.add(this.button.parents()).each(function(){
var color = $(this).css('backgroundColor');
var image = $(this).css('backgroundImage');
if ( color != 'transparent' || image != 'none'){
$(this).css('opacity', 1);
return false;
}
});
}
};
})(jQuery); |
Partager