/[drupal]/contributions/modules/swfupload/js/swfupload.src.js
ViewVC logotype

Contents of /contributions/modules/swfupload/js/swfupload.src.js

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.2 - (show annotations) (download) (as text)
Tue Nov 25 11:19:10 2008 UTC (12 months ago) by skilip
Branch: MAIN
CVS Tags: HEAD
Changes since 1.1: +22 -2 lines
File MIME type: text/javascript
Max upload size can now also be MB, GB etc.
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('&nbsp;');
193 var center_span = $('<div />').addClass('center');
194 var right_span = $('<div />').addClass('right').html('&nbsp;');
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 : '&nbsp;')));
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 : '&nbsp;'))).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('&nbsp;').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 });

  ViewVC Help
Powered by ViewVC 1.1.2