| 1 |
function SWFU(id, settings) {
|
| 2 |
var ref = {};
|
| 3 |
ref.settings = {};
|
| 4 |
|
| 5 |
ref.ajax_settings = {};
|
| 6 |
ref.queue = {};
|
| 7 |
ref.stats = {};
|
| 8 |
ref.instance = {};
|
| 9 |
ref.upload_stack_length = 0;
|
| 10 |
ref.max_queue_size = 0;
|
| 11 |
ref.upload_stack = {};
|
| 12 |
ref.upload_stack_obj;
|
| 13 |
ref.upload_button_obj;
|
| 14 |
ref.upload_stack_size = 0;
|
| 15 |
ref.wrapper_obj;
|
| 16 |
ref.num_elements;
|
| 17 |
ref.key_pressed;
|
| 18 |
ref.message_wrapper_obj;
|
| 19 |
ref.messages_timeout;
|
| 20 |
|
| 21 |
/**
|
| 22 |
*
|
| 23 |
*/
|
| 24 |
ref.init = function() {
|
| 25 |
ref.settings = settings;
|
| 26 |
ref.upload_button_obj = $('#edit-' + ref.settings.file_post_name);
|
| 27 |
ref.instance = {name:settings.file_post_name};
|
| 28 |
ref.ajax_settings = {
|
| 29 |
type:"post",
|
| 30 |
url:ref.settings.upload_url,
|
| 31 |
data:{
|
| 32 |
op:'init',
|
| 33 |
filepath:ref.settings.post_params.filepath,
|
| 34 |
instance:ref.toJson(ref.instance),
|
| 35 |
node_settings:ref.settings.post_params.node_settings
|
| 36 |
},
|
| 37 |
success:function(result) {
|
| 38 |
ref.ajaxResponse(result);
|
| 39 |
}
|
| 40 |
};
|
| 41 |
|
| 42 |
ref.prepareSWFButton();
|
| 43 |
// Get the instance data by an AJAX request in order to let other modules change the callbacks and elements for this instance (using hook_swfupload);
|
| 44 |
$.ajax(ref.ajax_settings);
|
| 45 |
|
| 46 |
// Firefox crashes here if swfupload.swf is loaded in a hidden collapsible fieldset.
|
| 47 |
// I haven't excacly found out what causes this, but commenting 'duration' in Drupal.toggleFieldset solved this.
|
| 48 |
// For now I'll overwrite the function.
|
| 49 |
if ($.browser.mozilla && $('.collapsible.collapsed').size() > 0) {
|
| 50 |
$.getScript(Drupal.settings.basePath + ref.settings.module_path + '/js/collapse.js');
|
| 51 |
};
|
| 52 |
};
|
| 53 |
|
| 54 |
/**
|
| 55 |
* Prepares the swfupload button.
|
| 56 |
*/
|
| 57 |
ref.prepareSWFButton = function() {
|
| 58 |
// Create a copy of the button to get it's dimensions.
|
| 59 |
// If we'd use the original button, we could end up with dimensions equal to 0px when the button is inside a hidden fieldset.
|
| 60 |
var tmp_button = ref.upload_button_obj.clone().css({'position':'absolute'}).prependTo('body');
|
| 61 |
|
| 62 |
// Set the dimensions of the swf so it matches exactly the dimensions of the upload button
|
| 63 |
// swfupload.swf will be placed exactly over the upload button
|
| 64 |
ref.settings.button_width = (tmp_button.find('.left').width() + tmp_button.find('.center').width() + tmp_button.find('.right').width());
|
| 65 |
ref.settings.button_height = tmp_button.find('.center').height();
|
| 66 |
tmp_button.remove();
|
| 67 |
|
| 68 |
// Add the other button settings to the settings object
|
| 69 |
ref.settings.button_placeholder_id = ref.settings.file_post_name + '-swfwrapper';
|
| 70 |
ref.settings.button_window_mode = SWFUpload.WINDOW_MODE.TRANSPARENT;
|
| 71 |
ref.settings.button_cursor = SWFUpload.CURSOR.HAND;
|
| 72 |
};
|
| 73 |
|
| 74 |
/**
|
| 75 |
* Creates a hidden input field which will contain a JSON formatted string containing all uploaded files
|
| 76 |
*/
|
| 77 |
ref.createStackObj = function() {
|
| 78 |
var upload_stack_value = settings.custom_settings.upload_stack_value;
|
| 79 |
ref.max_queue_size = settings.custom_settings.max_queue_size;
|
| 80 |
ref.upload_stack_obj = $('<input type="hidden" />').attr('name', ref.instance.name).val(upload_stack_value).prependTo(ref.upload_button_obj);
|
| 81 |
ref.upload_stack = Drupal.parseJson(upload_stack_value);
|
| 82 |
ref.upload_stack_length = ref.objectLength(ref.upload_stack);
|
| 83 |
};
|
| 84 |
|
| 85 |
/**
|
| 86 |
*
|
| 87 |
*/
|
| 88 |
ref.newSWFUpload = function() {
|
| 89 |
ref.swfu = new SWFUpload(ref.settings);
|
| 90 |
};
|
| 91 |
|
| 92 |
/**
|
| 93 |
*
|
| 94 |
*/
|
| 95 |
ref.ajaxResponse = function(result) {
|
| 96 |
var result = Drupal.parseJson(result);
|
| 97 |
|
| 98 |
switch (result.op) {
|
| 99 |
case 'init':
|
| 100 |
ref.instance = result.instance;
|
| 101 |
ref.num_elements = ref.objectLength(ref.instance.elements);
|
| 102 |
$.each(result.instance.callbacks, function(setting, callback) {
|
| 103 |
ref.settings[setting] = eval(callback);
|
| 104 |
});
|
| 105 |
ref.newSWFUpload();
|
| 106 |
ref.settings.init_complete_handler(result);
|
| 107 |
break;
|
| 108 |
};
|
| 109 |
ref.addEventHandlers(result.op);
|
| 110 |
};
|
| 111 |
|
| 112 |
/**
|
| 113 |
* Custom function for when the initialization is complete
|
| 114 |
* This event handler is defined in swfupload.module as an instance callback function
|
| 115 |
*/
|
| 116 |
ref.initComplete = function(result) {
|
| 117 |
ref.createWrapper(result.instance.name);
|
| 118 |
ref.createStackObj();
|
| 119 |
ref.addStoredFiles();
|
| 120 |
|
| 121 |
// Enable the upload button if the current stack is smaller than the allowed stack size.
|
| 122 |
if (ref.settings.file_upload_limit && ref.settings.file_upload_limit !== 0 && (ref.upload_stack_length < ref.settings.file_upload_limit)) {
|
| 123 |
ref.upload_button_obj.removeClass('disabled').css({opacity:1});
|
| 124 |
}
|
| 125 |
else {
|
| 126 |
ref.upload_button_obj.addClass('disabled').css({opacity:0.4});
|
| 127 |
};
|
| 128 |
};
|
| 129 |
|
| 130 |
/**
|
| 131 |
* This will process all file elements stored in the upload stack.
|
| 132 |
* The upload represents all files submitted in the upload form.
|
| 133 |
* For all files in the stack, a file element will be added to the wrapper using ref.addFileItem().
|
| 134 |
*/
|
| 135 |
ref.addStoredFiles = function() {
|
| 136 |
for(var i in ref.upload_stack) {
|
| 137 |
if (ref.upload_stack[i] == 0) {
|
| 138 |
break;
|
| 139 |
};
|
| 140 |
ref.upload_stack[i].id = i;
|
| 141 |
ref.upload_stack[i].fid = i;
|
| 142 |
ref.upload_stack[i].extension = ref.getExtension(ref.upload_stack[i].filename);
|
| 143 |
ref.addFileItem(ref.upload_stack[i]);
|
| 144 |
|
| 145 |
// Adjust the bytes in the stack.
|
| 146 |
ref.upload_stack_size += parseInt(ref.upload_stack[i].filesize);
|
| 147 |
};
|
| 148 |
ref.dragEnable();
|
| 149 |
};
|
| 150 |
|
| 151 |
/**
|
| 152 |
* Places the wrapper markup above the upload button
|
| 153 |
* Depending on what type isset by the instance, a table or a list element is created.
|
| 154 |
*/
|
| 155 |
ref.createWrapper = function(name) {
|
| 156 |
var use_header = false;
|
| 157 |
var element;
|
| 158 |
|
| 159 |
if (ref.num_elements > 1 && ref.instance.type == 'table') {
|
| 160 |
// First we'll check if we need to create a header
|
| 161 |
for (var name in ref.instance.elements) {
|
| 162 |
if (ref.instance.elements[name].title) {
|
| 163 |
use_header = true;
|
| 164 |
};
|
| 165 |
};
|
| 166 |
|
| 167 |
ref.wrapper_obj = $('<table />').attr({'id':'swfupload_file_wrapper-' + name, 'class':'swfupload'});
|
| 168 |
if (use_header) {
|
| 169 |
ref.wrapper_obj.append($('<thead />').append(ref.tableRow(true)));
|
| 170 |
};
|
| 171 |
ref.wrapper_obj.append($('<tbody />').append(ref.tableRow()));
|
| 172 |
ref.upload_button_obj.before(ref.wrapper_obj);
|
| 173 |
};
|
| 174 |
};
|
| 175 |
|
| 176 |
/**
|
| 177 |
* Creates or changes a tablerow
|
| 178 |
* @param header Boolean Wheter or not the tablerow should contain th's. If sety to false, td's will be generated.
|
| 179 |
* @param file Object A completed file object
|
| 180 |
* If this is not set, a row is created including the progressbar, which replaces the td's with contains_progressbar set to true.
|
| 181 |
* If file is set, the progressbar will be replaced with the appropriate td's
|
| 182 |
*/
|
| 183 |
ref.tableRow = function(header, file) {
|
| 184 |
var counter = 0;
|
| 185 |
var colspan = 0;
|
| 186 |
var fid = (file) ? file.fid : 0;
|
| 187 |
var progress_td_counter = 0;
|
| 188 |
var element, colum, content, input, progress_td, value;
|
| 189 |
|
| 190 |
var tr = (file) ? $('#' + file.fid) : $('<tr />');
|
| 191 |
var wrapper = $('<div />').addClass('wrapper');
|
| 192 |
var left_span = $('<div />').addClass('left').html(' ');
|
| 193 |
var center_span = $('<div />').addClass('center');
|
| 194 |
var right_span = $('<div />').addClass('right').html(' ');
|
| 195 |
|
| 196 |
// A tablerow will be created containing all elements defined in ref.instance.elements.
|
| 197 |
// If file is set, all elements will be skipped exept the ones with 'contains_progressbar'
|
| 198 |
// If file isn't set, this tablerow will be hidden.
|
| 199 |
for (var name in ref.instance.elements) {
|
| 200 |
counter++;
|
| 201 |
element = ref.instance.elements[name];
|
| 202 |
|
| 203 |
if (file) {
|
| 204 |
if(!element.contains_progressbar) {
|
| 205 |
// The current td doesn't have to be replaced.
|
| 206 |
// We only need to replace fid of the id and name of the input field
|
| 207 |
tr.find('#edit-' + name + '_0').attr({'name':name +'_' + fid, 'id':'edit-' + name + '_' + fid});
|
| 208 |
continue;
|
| 209 |
};
|
| 210 |
}
|
| 211 |
else {
|
| 212 |
if (!header && element.contains_progressbar) {
|
| 213 |
if (!progress_td) {
|
| 214 |
progress_td = $('<td />').addClass('progress').append($('<div />').addClass('sfwupload-list-progressbar').append($('<div />').addClass('sfwupload-list-progressbar-status')).append($('<div />').addClass('sfwupload-list-progressbar-glow'))).appendTo(tr);
|
| 215 |
};
|
| 216 |
progress_td_counter++;
|
| 217 |
continue;
|
| 218 |
};
|
| 219 |
};
|
| 220 |
|
| 221 |
column = $((header ? '<th />' : '<td />'));
|
| 222 |
content = wrapper.clone().appendTo(column);
|
| 223 |
input = $((element.type == 'textarea' ? '<textarea />' : '<input type="' + element.type + '" />')).attr({'name':name +'_' + fid, 'id':'edit-' + name + '_' + fid}).addClass('form-' + element.type);
|
| 224 |
|
| 225 |
if (header) {
|
| 226 |
// Keep track of colspans
|
| 227 |
if (colspan > 0) colspan--;
|
| 228 |
if (element.colspan) {
|
| 229 |
colspan = element.colspan;
|
| 230 |
}
|
| 231 |
else if (colspan !== 0) {
|
| 232 |
continue;
|
| 233 |
};
|
| 234 |
|
| 235 |
// Add the colspan if set.
|
| 236 |
if (element.colspan) {
|
| 237 |
column.attr({'colSpan':element.colspan});
|
| 238 |
};
|
| 239 |
|
| 240 |
// Add a separator only if we're not dealing with the first or last column
|
| 241 |
if (counter !== ref.num_elements && (counter + (colspan - 1) !== ref.num_elements) && element.add_separator) {
|
| 242 |
content.append(left_span.clone()).append(right_span.clone());
|
| 243 |
};
|
| 244 |
|
| 245 |
content.append(center_span.clone().html((element.title ? element.title : ' ')));
|
| 246 |
}
|
| 247 |
else {
|
| 248 |
// Create the content for this td
|
| 249 |
// Depending on the type the appropriate input field is appended to store the values of this type
|
| 250 |
switch (element.type) {
|
| 251 |
case 'drag':
|
| 252 |
content.append($('<div />').addClass('sfwupload-list-drag'));
|
| 253 |
|
| 254 |
// Fix transparency for IE6
|
| 255 |
if ($.cssPNGFix) {
|
| 256 |
content.find('.sfwupload-list-drag').cssPNGFix();
|
| 257 |
};
|
| 258 |
break;
|
| 259 |
case 'icon':
|
| 260 |
content.append($('<div />').addClass('sfwupload-list-mime'));
|
| 261 |
break;
|
| 262 |
case 'cancel':
|
| 263 |
content.append($('<div />').addClass('sfwupload-list-cancel'));
|
| 264 |
break;
|
| 265 |
case 'text':
|
| 266 |
value = (file) ? (file[name] !== undefined) ? file[name] : ref.replaceMacros(element.default_value, file) : element.default_value;
|
| 267 |
content.append($('<span />').html(value)).append(input.css({'display':'none'}).val(value));
|
| 268 |
break;
|
| 269 |
case 'textarea':
|
| 270 |
value = (file) ? (file[name] !== undefined) ? file[name] : ref.replaceMacros(element.default_value, file) : element.default_value;
|
| 271 |
content.append($('<span />').html((value !== '' ? value : ' '))).append(input.css({'display':'none'}).val(value));
|
| 272 |
break;
|
| 273 |
case 'checkbox':
|
| 274 |
value = (file[name] !== undefined) ? (typeof(file[name]) == 'string' ? (file[name] == '1') : file[name]) : element.default_value;
|
| 275 |
// For IE we need to check the checkbox after the content has been added to the tr.
|
| 276 |
// We'll temporarily store it's value in a classname
|
| 277 |
content.append(input.addClass('checkbox ' + (value ? 'checked' : '')));
|
| 278 |
break;
|
| 279 |
default:
|
| 280 |
break;
|
| 281 |
};
|
| 282 |
};
|
| 283 |
|
| 284 |
// Add a classname if set.
|
| 285 |
if (element.classname) {
|
| 286 |
column.addClass(element.classname);
|
| 287 |
};
|
| 288 |
|
| 289 |
if (file && element.contains_progressbar) {
|
| 290 |
column.insertBefore(tr.find('td.progress'));
|
| 291 |
}
|
| 292 |
else {
|
| 293 |
tr.append(column);
|
| 294 |
};
|
| 295 |
};
|
| 296 |
|
| 297 |
if (!header && !file) {
|
| 298 |
// Hide the tablerow
|
| 299 |
tr.addClass('hidden');
|
| 300 |
};
|
| 301 |
|
| 302 |
if (progress_td) {
|
| 303 |
progress_td.attr({'colSpan':progress_td_counter});
|
| 304 |
};
|
| 305 |
|
| 306 |
// Update the checked value of all added checkboxes
|
| 307 |
tr.find('input.checkbox').each(function() {
|
| 308 |
$(this).attr('checked', $(this).hasClass('checked'));
|
| 309 |
});
|
| 310 |
|
| 311 |
if (file) {
|
| 312 |
tr.addClass('processed').find('td.progress').remove();
|
| 313 |
}
|
| 314 |
else {
|
| 315 |
// Create borders
|
| 316 |
var border = $(header ? '<th />' : '<td />').addClass('border').append($('<img />').attr({'src':Drupal.settings.basePath + ref.settings.module_path + '/images/spacer.gif'}).css({'width':'1px'}));
|
| 317 |
tr.prepend(border.clone()).append(border);
|
| 318 |
return tr;
|
| 319 |
};
|
| 320 |
};
|
| 321 |
|
| 322 |
/**
|
| 323 |
* A file has been selected. This function creates the markup referring to the new file object
|
| 324 |
*/
|
| 325 |
ref.addFileItem = function(file) {
|
| 326 |
// Create the markup for the new file by copying the hidden template
|
| 327 |
var new_file_obj = ref.wrapper_obj.find('.hidden').clone().attr({'id':file.id}).appendTo(ref.wrapper_obj);
|
| 328 |
var input, value;
|
| 329 |
|
| 330 |
// If it is a file earlier stored (a file in the upload_stack), remove it's progressbar.
|
| 331 |
if (file.filestatus !== -1) {
|
| 332 |
ref.tableRow(false, file);
|
| 333 |
};
|
| 334 |
|
| 335 |
// Replace macro's
|
| 336 |
for (var name in ref.instance.elements) {
|
| 337 |
input = new_file_obj.find('#edit-' + name + '_' + (file.fid || '0'));
|
| 338 |
if (input.size() > 0) {
|
| 339 |
value = (file[name] !== undefined) ? file[name] : ref.replaceMacros(ref.instance.elements[name].default_value, file);
|
| 340 |
input.val(value);
|
| 341 |
// If the inputfield is hidden, we're dealing with a string.
|
| 342 |
// Look if there is a span of which the text can be replaced
|
| 343 |
if (input.css('display') == 'none') {
|
| 344 |
input.parent().find('span').text(value);
|
| 345 |
};
|
| 346 |
};
|
| 347 |
};
|
| 348 |
// Add the extension to the mime icon
|
| 349 |
new_file_obj.find('.sfwupload-list-mime').addClass(file.extension);
|
| 350 |
|
| 351 |
// Fix transparency for IE6
|
| 352 |
if ($.cssPNGFix) {
|
| 353 |
new_file_obj.find('.sfwupload-list-mime').cssPNGFix();
|
| 354 |
};
|
| 355 |
|
| 356 |
new_file_obj.removeClass('hidden');
|
| 357 |
ref.addEventHandlers((file.filestatus == -1 ? 'file_queued' : 'file_added'), file);
|
| 358 |
};
|
| 359 |
|
| 360 |
/**
|
| 361 |
* Attaches all event handlers to the loaded markup
|
| 362 |
*/
|
| 363 |
ref.addEventHandlers = function(op, file) {
|
| 364 |
switch (op) {
|
| 365 |
case 'flash_loaded':
|
| 366 |
ref.upload_button_obj.find('.swfupload-wrapper .swfupload').mousedown(function() {
|
| 367 |
$(this).parent().parent().addClass('active');
|
| 368 |
}).mouseup(function() {
|
| 369 |
$(this).parent().parent().removeClass('active');
|
| 370 |
});
|
| 371 |
break;
|
| 372 |
case 'file_queued':
|
| 373 |
$('#' + file.id).find('.sfwupload-list-cancel').click(function() {
|
| 374 |
ref.cancelUpload(file);
|
| 375 |
});
|
| 376 |
break;
|
| 377 |
case 'file_added':
|
| 378 |
$('#' + file.fid).find('.sfwupload-list-cancel').unbind('click').click(function() {
|
| 379 |
ref.deleteFile(file);
|
| 380 |
});
|
| 381 |
$('#' + file.fid).find('input:checkbox').bind('click', function() {
|
| 382 |
ref.updateStack(file);
|
| 383 |
});
|
| 384 |
$('#' + file.fid).find('input:text, textarea').blur(function() {
|
| 385 |
ref.toggleInput($(this), false, file);
|
| 386 |
}).keydown(function(e) {
|
| 387 |
ref.key_pressed = e.keyCode;
|
| 388 |
if ((e.keyCode == 27) || (e.keyCode == 13 && $(this).get(0).tagName.toLowerCase() !== 'textarea')) {
|
| 389 |
$(this).blur();
|
| 390 |
return false;
|
| 391 |
};
|
| 392 |
}).parent().find('span').dblclick(function() {
|
| 393 |
ref.toggleInput($(this), true, file);
|
| 394 |
});
|
| 395 |
break;
|
| 396 |
default:
|
| 397 |
break;
|
| 398 |
};
|
| 399 |
};
|
| 400 |
|
| 401 |
/**
|
| 402 |
* Toggles editability of text spans inside tablerows
|
| 403 |
*/
|
| 404 |
ref.toggleInput = function(obj, start, file) {
|
| 405 |
if (start) {
|
| 406 |
obj.hide().parent().find('input:text, textarea').show().focus().select();
|
| 407 |
}
|
| 408 |
else {
|
| 409 |
if (ref.key_pressed == 27) {
|
| 410 |
obj.val(obj.parent().find('span').html()).hide().parent().find('span').show();
|
| 411 |
return;
|
| 412 |
};
|
| 413 |
|
| 414 |
var value = obj.val();
|
| 415 |
if (value == '') {
|
| 416 |
obj.hide().parent().find('span').html(' ').show();
|
| 417 |
}
|
| 418 |
else {
|
| 419 |
obj.hide().parent().find('span').text(value).show();
|
| 420 |
};
|
| 421 |
};
|
| 422 |
ref.updateStack(file);
|
| 423 |
};
|
| 424 |
|
| 425 |
/**
|
| 426 |
* Makes tablerows sortable.
|
| 427 |
*/
|
| 428 |
ref.dragEnable = function() {
|
| 429 |
// Move on only if the plugin tableDnD exists.
|
| 430 |
if ($.tableDnD == undefined) {
|
| 431 |
return;
|
| 432 |
};
|
| 433 |
|
| 434 |
var enable = (ref.wrapper_obj.find('tbody tr:not(.hidden)').size() > 1);
|
| 435 |
var cursor = (enable) ? 'move' : 'default';
|
| 436 |
var visibility = (enable) ? 'visible' : 'hidden';
|
| 437 |
|
| 438 |
$('.sfwupload-list-drag').css({'visibility':visibility}).parents('.drag').css({'cursor':cursor});
|
| 439 |
|
| 440 |
if (!enable) {
|
| 441 |
$('.drag').unbind('mousedown');
|
| 442 |
return;
|
| 443 |
};
|
| 444 |
ref.wrapper_obj.tableDnD({
|
| 445 |
dragHandle:'drag',
|
| 446 |
onDragClass:'dragging',
|
| 447 |
onDrop:function() {
|
| 448 |
ref.updateStack();
|
| 449 |
}
|
| 450 |
});
|
| 451 |
};
|
| 452 |
|
| 453 |
/**
|
| 454 |
* Launched when the swf has been loaded.
|
| 455 |
*/
|
| 456 |
ref.swfUploadLoaded = function() {
|
| 457 |
// Update the stats object in order to let SWFUpload know we've already got some files stored
|
| 458 |
ref.swfu.setStats({successful_uploads: ref.upload_stack_length});
|
| 459 |
ref.addEventHandlers('flash_loaded');
|
| 460 |
};
|
| 461 |
|
| 462 |
/**
|
| 463 |
* The file(s) have been selected.
|
| 464 |
*/
|
| 465 |
ref.dialogComplete = function(files_selected, files_queued) {
|
| 466 |
if (ref.settings.file_upload_limit && ref.settings.file_upload_limit !== 0 && (files_selected > ref.settings.file_upload_limit)) {
|
| 467 |
ref.displayMessage(Drupal.t('You can upload only !num !file!', {'!num':ref.settings.file_upload_limit, '!file':Drupal.formatPlural(ref.settings.file_upload_limit, 'file', 'files')}), 'error');
|
| 468 |
}
|
| 469 |
else {
|
| 470 |
ref.uploadNextInQueue();
|
| 471 |
};
|
| 472 |
};
|
| 473 |
|
| 474 |
/**
|
| 475 |
* The file(s) have been selected by the user and added to the upload queue
|
| 476 |
*/
|
| 477 |
ref.fileQueued = function(file) {
|
| 478 |
if (ref.settings.file_upload_limit && ref.settings.file_upload_limit !== 0) {
|
| 479 |
// Check if the queued file(s) do not exceed the max number of files
|
| 480 |
var stats = ref.swfu.getStats();
|
| 481 |
if ((ref.upload_stack_length + stats.files_queued) > ref.settings.file_upload_limit) {
|
| 482 |
ref.swfu.cancelUpload(file.id);
|
| 483 |
var queue_space = (ref.settings.file_upload_limit - ref.upload_stack_length);
|
| 484 |
if (queue_space == 0) {
|
| 485 |
ref.displayMessage(Drupal.t('You are not allowed to add more than !num !file!', {'!num':ref.settings.file_upload_limit, '!file':Drupal.formatPlural(ref.settings.file_upload_limit, 'file', 'files')}), 'error');
|
| 486 |
}
|
| 487 |
else {
|
| 488 |
ref.displayMessage(Drupal.t('You can upload only !num more !file!', {'!num':queue_space, '!file':Drupal.formatPlural(queue_space, 'file', 'files')}), 'error');
|
| 489 |
};
|
| 490 |
return;
|
| 491 |
};
|
| 492 |
};
|
| 493 |
if (ref.max_queue_size && ref.max_queue_size !== 0) {
|
| 494 |
// Check if the new file does not exceed the max queue size
|
| 495 |
if ((ref.upload_stack_size + file.size) > ref.max_queue_size) {
|
| 496 |
var max_queue_mbs = ref.getMbs(ref.max_queue_size);
|
| 497 |
var file_mbs = ((file.size / 1024) / 1024);
|
| 498 |
ref.swfu.cancelUpload(file.id);
|
| 499 |
ref.displayMessage(Drupal.t('The file size (!num1 MB) exceeds the upload size (!num2 MB) for this page!', {'!num1':file_mbs.toFixed(2), '!num2':max_queue_mbs.toFixed(2)}), 'error');
|
| 500 |
return;
|
| 501 |
};
|
| 502 |
};
|
| 503 |
// No problems found, add the new file to the stack.
|
| 504 |
file.extension = ref.getExtension(file.name);
|
| 505 |
ref.queue[file.id] = file;
|
| 506 |
ref.addFileItem(file);
|
| 507 |
};
|
| 508 |
|
| 509 |
/**
|
| 510 |
* Responds on file queue errors
|
| 511 |
*/
|
| 512 |
ref.fileQueueError = function(file, code, message) {
|
| 513 |
switch (code) {
|
| 514 |
case -110: // The file selected is too large
|
| 515 |
var max_file_mbs = ref.getMbs(ref.settings.file_size_limit);
|
| 516 |
var file_mbs = ((file.size / 1024) / 1024);
|
| 517 |
ref.displayMessage(Drupal.t('The file size (!num1 MB) exceeds the file size limit (!num2 MB)!', {'!num1':file_mbs.toFixed(2), '!num2':max_file_mbs.toFixed(2)}), 'error');
|
| 518 |
break;
|
| 519 |
default:
|
| 520 |
break;
|
| 521 |
};
|
| 522 |
};
|
| 523 |
|
| 524 |
/**
|
| 525 |
* Calculates the MB's from a given string
|
| 526 |
*/
|
| 527 |
ref.getMbs = function(size) {
|
| 528 |
// B, KB, MB and GB
|
| 529 |
if (size.indexOf('MB') > -1) {
|
| 530 |
return parseInt(size);
|
| 531 |
}
|
| 532 |
else if (size.indexOf('GB') > -1) {
|
| 533 |
return (parseInt(size) * 1024);
|
| 534 |
}
|
| 535 |
else if (size.indexOf('KB') > -1) {
|
| 536 |
return (parseInt(size) / 1024);
|
| 537 |
}
|
| 538 |
else if (size.indexOf('B') > -1) {
|
| 539 |
return ((parseInt(size) / 1024) / 1024);
|
| 540 |
};
|
| 541 |
return false;
|
| 542 |
};
|
| 543 |
|
| 544 |
/**
|
| 545 |
* Displays messages
|
| 546 |
*/
|
| 547 |
ref.displayMessage = function(message, type) {
|
| 548 |
if (!ref.message_wrapper_obj) {
|
| 549 |
ref.message_wrapper_obj = $('<div />').addClass('messages swfupload').insertAfter(ref.wrapper_obj);
|
| 550 |
|
| 551 |
ref.message_wrapper_obj.css({'height':'auto', 'opacity':1}).removeClass('status error').addClass(type).html(message);
|
| 552 |
ref.messages_timeout = setTimeout(function() {ref.hideMessages();}, 5000);
|
| 553 |
}
|
| 554 |
else {
|
| 555 |
// The messagewrapper already exists. Add the new message to the wrapper and reset the timeout.
|
| 556 |
|
| 557 |
// Check if the message isn't already displayed
|
| 558 |
if (ref.message_wrapper_obj.html().indexOf(message) > -1) {
|
| 559 |
return;
|
| 560 |
};
|
| 561 |
|
| 562 |
// If the new type differs from the current type, we'll remove the old message.
|
| 563 |
if ((ref.message_wrapper_obj.hasClass('status') && type !== 'status') || (ref.message_wrapper_obj.hasClass('error') && type !== 'error')) {
|
| 564 |
ref.message_wrapper_obj.removeClass('status error').addClass(type).html(message);
|
| 565 |
}
|
| 566 |
else {
|
| 567 |
ref.message_wrapper_obj.append('<br />' + message);
|
| 568 |
};
|
| 569 |
clearInterval(ref.messages_timeout);
|
| 570 |
ref.messages_timeout = setTimeout(function() {ref.hideMessages();}, 5000);
|
| 571 |
};
|
| 572 |
};
|
| 573 |
|
| 574 |
/**
|
| 575 |
* Slowly hides the messages wrapper
|
| 576 |
*/
|
| 577 |
ref.hideMessages = function() {
|
| 578 |
ref.message_wrapper_obj.animate({'height':'0px', 'opacity':0}, 'slow', function() {
|
| 579 |
ref.message_wrapper_obj.remove();
|
| 580 |
ref.message_wrapper_obj = false;
|
| 581 |
});
|
| 582 |
};
|
| 583 |
|
| 584 |
/**
|
| 585 |
* Triggers a new upload.
|
| 586 |
*/
|
| 587 |
ref.uploadNextInQueue = function() {
|
| 588 |
try {
|
| 589 |
ref.swfu.startUpload();
|
| 590 |
}
|
| 591 |
catch (err) {
|
| 592 |
ref.swfu.debug(err);
|
| 593 |
};
|
| 594 |
};
|
| 595 |
|
| 596 |
/**
|
| 597 |
* Adjusts the progress indicator.
|
| 598 |
*/
|
| 599 |
ref.uploadProgress = function(file, complete, total) {
|
| 600 |
// We don't want this one to end up to 100% when all bytes are loaded. The progressbar will have an width of 100% on uploadFileComplete
|
| 601 |
var done = Math.round((96 / total) * complete);
|
| 602 |
$('#' + file.id + ' .sfwupload-list-progressbar-status').css({'width':done + '%'});
|
| 603 |
};
|
| 604 |
|
| 605 |
/**
|
| 606 |
* Handles upload errors
|
| 607 |
*/
|
| 608 |
ref.uploadError = function(file, code, message) {
|
| 609 |
// Check for messages which can be handled as 'status' messages
|
| 610 |
switch (code) {
|
| 611 |
case -240:
|
| 612 |
ref.displayMessage(Drupal.t('The upload limit (!num) has been reached!', {'!num':ref.settings.file_upload_limit}), 'status');
|
| 613 |
return;
|
| 614 |
case -200:
|
| 615 |
message = Drupal.t('Server error!', {'!num':ref.settings.file_upload_limit});
|
| 616 |
};
|
| 617 |
|
| 618 |
// Give the user some visual indicators of the event
|
| 619 |
$('#' + file.id + ' .sfwupload-list-progressbar').addClass('stopped').find('.sfwupload-list-progressbar-status').css({'width':'100%'});
|
| 620 |
$('#' + file.id + ' .sfwupload-list-progressbar-glow').append((typeof(message) == 'object' ? message[0] : message));
|
| 621 |
|
| 622 |
// If a file is set, we need to remove the added file DOM element
|
| 623 |
if (file) {
|
| 624 |
setTimeout(function() {
|
| 625 |
ref.removeFileItem(file);
|
| 626 |
}, 2000);
|
| 627 |
};
|
| 628 |
};
|
| 629 |
|
| 630 |
/**
|
| 631 |
* Triggered after the upload is succesfully completed.
|
| 632 |
*/
|
| 633 |
ref.uploadComplete = function(file) {
|
| 634 |
if (ref.queue[file.id] && !ref.queue[file.id].cancelled) {
|
| 635 |
setTimeout(function() {
|
| 636 |
$('#' + ref.queue[file.id].fid).find('.sfwupload-list-progressbar').animate({'opacity':0}, "slow", function() {
|
| 637 |
file.fid = ref.queue[file.id].fid;
|
| 638 |
ref.tableRow(false, file);
|
| 639 |
ref.updateStack(file);
|
| 640 |
ref.addEventHandlers('file_added', file);
|
| 641 |
});
|
| 642 |
}, 1000);
|
| 643 |
};
|
| 644 |
ref.uploadNextInQueue();
|
| 645 |
};
|
| 646 |
|
| 647 |
/**
|
| 648 |
* Retrieves the data returned by the server
|
| 649 |
*/
|
| 650 |
ref.uploadSuccess = function(file, server_data) {
|
| 651 |
var server_data = Drupal.parseJson(server_data);
|
| 652 |
|
| 653 |
// Check for messages returned by the server.
|
| 654 |
if (server_data.messages) {
|
| 655 |
|
| 656 |
// Check if the server returned an error
|
| 657 |
if (server_data.messages.error) {
|
| 658 |
ref.uploadError(file, null, server_data.messages.error);
|
| 659 |
ref.queue[file.id].cancelled = true;
|
| 660 |
return;
|
| 661 |
};
|
| 662 |
|
| 663 |
// Check if the server returned status messages
|
| 664 |
if (server_data.messages.status) {
|
| 665 |
for (var i in server_data.messages.status) {
|
| 666 |
ref.displayMessage(server_data.messages.status[i], 'status');
|
| 667 |
};
|
| 668 |
};
|
| 669 |
};
|
| 670 |
|
| 671 |
// No errors. Complete the fileupload.
|
| 672 |
ref.queue[file.id].fid = server_data.file.fid;
|
| 673 |
$('#' + file.id).attr({'id':server_data.file.fid}).find('.sfwupload-list-progressbar-status').css({'width':'100%'}).parent().addClass('complete');
|
| 674 |
};
|
| 675 |
|
| 676 |
/**
|
| 677 |
* Updates the value of the hidden input field which stores all uploaded files
|
| 678 |
*/
|
| 679 |
ref.updateStack = function(file) {
|
| 680 |
var fid, input_field, element;
|
| 681 |
var old_upload_stack = ref.upload_stack;
|
| 682 |
var total_size = 0;
|
| 683 |
ref.upload_stack = {};
|
| 684 |
|
| 685 |
ref.wrapper_obj.find('.processed').each(function() {
|
| 686 |
fid = $(this).attr('id');
|
| 687 |
|
| 688 |
// If no file is secified, the function is called after sorting
|
| 689 |
// There are no new values so the file object is not needed
|
| 690 |
// We only need to change the order of the stack
|
| 691 |
if (!file) {
|
| 692 |
ref.upload_stack[fid] = old_upload_stack[fid];
|
| 693 |
}
|
| 694 |
else {
|
| 695 |
ref.upload_stack[fid] = {filename:file.filename || file.name, fid:fid};
|
| 696 |
total_size += parseInt(file.size);
|
| 697 |
for (var name in ref.instance.elements) {
|
| 698 |
input_field = $('#edit-' + name + '_' + fid);
|
| 699 |
if (input_field.size() !== 0) {
|
| 700 |
ref.upload_stack[fid][name] = (input_field.attr('type') == 'checkbox') ? input_field.attr('checked') : input_field.val();
|
| 701 |
};
|
| 702 |
};
|
| 703 |
};
|
| 704 |
});
|
| 705 |
ref.upload_stack_size = total_size;
|
| 706 |
ref.upload_stack_length = ref.objectLength(ref.upload_stack);
|
| 707 |
ref.upload_stack_obj.val(ref.toJson(ref.upload_stack));
|
| 708 |
ref.dragEnable();
|
| 709 |
|
| 710 |
if (ref.settings.file_upload_limit > ref.upload_stack_length) {
|
| 711 |
ref.upload_button_obj.removeClass('disabled').css({opacity:1});
|
| 712 |
}
|
| 713 |
else {
|
| 714 |
ref.upload_button_obj.addClass('disabled').css({opacity:0.4});
|
| 715 |
};
|
| 716 |
};
|
| 717 |
|
| 718 |
/**
|
| 719 |
* Aborts a file upload
|
| 720 |
*/
|
| 721 |
ref.cancelUpload = function(file) {
|
| 722 |
// Check if the file is still being uploaded.
|
| 723 |
if (ref.swfu.getFile(file.id)) {
|
| 724 |
// Abort the upload
|
| 725 |
ref.swfu.cancelUpload(file.id);
|
| 726 |
ref.queue[file.id].cancelled = true;
|
| 727 |
setTimeout(function() {
|
| 728 |
ref.removeFileItem(file);
|
| 729 |
}, 1000);
|
| 730 |
}
|
| 731 |
};
|
| 732 |
|
| 733 |
/**
|
| 734 |
* Deletes an uploaded file from the list
|
| 735 |
*/
|
| 736 |
ref.deleteFile = function(file) {
|
| 737 |
if (confirm(Drupal.t('Are you sure you want to delete !name? This action can not be undone!', {'!name':file.name}))) {
|
| 738 |
ref.removeFileItem(file);
|
| 739 |
};
|
| 740 |
};
|
| 741 |
|
| 742 |
/**
|
| 743 |
* Removes a file form the list
|
| 744 |
*/
|
| 745 |
ref.removeFileItem = function(file) {
|
| 746 |
var file_tr = $('#' + (file.fid ? file.fid : file.id)).removeClass('processed');
|
| 747 |
var file_tds = file_tr.find('td');
|
| 748 |
var current_height = file_tr.height();
|
| 749 |
var cleared = false;
|
| 750 |
|
| 751 |
// Delete the file from the queue
|
| 752 |
delete(ref.queue[file.id]);
|
| 753 |
|
| 754 |
// Animate the deletion of the file's table row
|
| 755 |
// First fade out the contents of the td's
|
| 756 |
file_tds.find('div, input').animate({opacity:0}, 'fast', function() {
|
| 757 |
file_tds.each(function() {
|
| 758 |
// The contents are not visible anymore, so we can remove it.
|
| 759 |
$(this).html('');
|
| 760 |
});
|
| 761 |
|
| 762 |
// Since animate({height:0}) does not work for tr and td's, we need to declare our own interval
|
| 763 |
var intv = setInterval(function() {
|
| 764 |
current_height -= 5;
|
| 765 |
file_tds.height(current_height);
|
| 766 |
file_tr.css({opacity: current_height * 4});
|
| 767 |
|
| 768 |
// The animation is complete
|
| 769 |
if(current_height <= 5) {
|
| 770 |
if (!cleared) {
|
| 771 |
cleared = true;
|
| 772 |
file_tr.remove();
|
| 773 |
clearInterval(intv);
|
| 774 |
|
| 775 |
// Reset the successfull upload queue
|
| 776 |
var stats = ref.swfu.getStats();
|
| 777 |
stats.successful_uploads--;
|
| 778 |
ref.swfu.setStats(stats);
|
| 779 |
|
| 780 |
if (file_tr) {
|
| 781 |
// Update the hidden input field
|
| 782 |
ref.updateStack(file);
|
| 783 |
};
|
| 784 |
};
|
| 785 |
};
|
| 786 |
}, 50);
|
| 787 |
});
|
| 788 |
};
|
| 789 |
|
| 790 |
/**
|
| 791 |
* Retrieve the number of elements in an object
|
| 792 |
*/
|
| 793 |
ref.objectLength = function(obj) {
|
| 794 |
if (obj.status !== undefined && obj.status == 0) return 0;
|
| 795 |
|
| 796 |
var count = 0;
|
| 797 |
for (var i in obj)
|
| 798 |
count++;
|
| 799 |
return count;
|
| 800 |
};
|
| 801 |
|
| 802 |
/**
|
| 803 |
* Parses an object to a json formatted string
|
| 804 |
*/
|
| 805 |
ref.toJson = function(v) {
|
| 806 |
switch (typeof v) {
|
| 807 |
case 'boolean':
|
| 808 |
return v == true ? 'true' : 'false';
|
| 809 |
case 'number':
|
| 810 |
return v;
|
| 811 |
case 'string':
|
| 812 |
return '"'+ v.replace(/\n/g, '\\n') +'"';
|
| 813 |
case 'object':
|
| 814 |
var output = "{";
|
| 815 |
for(i in v) {
|
| 816 |
output = output + '"' + i + '"' + ":" + ref.toJson(v[i]) + ",";
|
| 817 |
}
|
| 818 |
output = output.substr(0, output.length - 1) + "}";
|
| 819 |
return (output == '}') ? 'null' : output;
|
| 820 |
default:
|
| 821 |
return 'null';
|
| 822 |
};
|
| 823 |
};
|
| 824 |
|
| 825 |
/**
|
| 826 |
*
|
| 827 |
*/
|
| 828 |
ref.getExtension = function(file_name) {
|
| 829 |
return file_name.substring(file_name.lastIndexOf('.') + 1).toLowerCase();
|
| 830 |
};
|
| 831 |
|
| 832 |
/**
|
| 833 |
* Replaces default values from ref.instance.elements to file values
|
| 834 |
* @see ref.uploadComplete
|
| 835 |
*/
|
| 836 |
ref.replaceMacros = function(value, file) {
|
| 837 |
if (!value || value == 0) {
|
| 838 |
return false;
|
| 839 |
}
|
| 840 |
else if (value == 1) {
|
| 841 |
return true;
|
| 842 |
}
|
| 843 |
else {
|
| 844 |
var macros = {'{filename}':file.name, '{fid}':file.fid};
|
| 845 |
for (var i in macros) {
|
| 846 |
value = value.replace(i, macros[i]);
|
| 847 |
};
|
| 848 |
return value;
|
| 849 |
};
|
| 850 |
};
|
| 851 |
|
| 852 |
/**
|
| 853 |
* Reverses the order of an object
|
| 854 |
*/
|
| 855 |
ref.objReverse = function(obj) {
|
| 856 |
var temp_arr = [];
|
| 857 |
var temp_obj = {};
|
| 858 |
|
| 859 |
for (var i in obj) {
|
| 860 |
temp_arr.push({key:i, data:obj[i]});
|
| 861 |
};
|
| 862 |
temp_arr = temp_arr.reverse();
|
| 863 |
for (var i in temp_arr) {
|
| 864 |
temp_obj[temp_arr[i].key] = temp_arr[i].data;
|
| 865 |
};
|
| 866 |
return temp_obj;
|
| 867 |
};
|
| 868 |
|
| 869 |
return ref;
|
| 870 |
};
|
| 871 |
|
| 872 |
$(function() {
|
| 873 |
if (Drupal.settings.swfupload_settings) {
|
| 874 |
Drupal.swfu = {};
|
| 875 |
var settings = Drupal.settings.swfupload_settings;
|
| 876 |
|
| 877 |
for (var id in settings) {
|
| 878 |
Drupal.swfu[id] = new SWFU(id, settings[id]);
|
| 879 |
Drupal.swfu[id].init();
|
| 880 |
};
|
| 881 |
};
|
| 882 |
});
|