plupload-rails 1.0.6 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (71) hide show
  1. checksums.yaml +7 -0
  2. data/GPL-LICENSE.txt +278 -0
  3. data/MIT-LICENSE.txt +20 -0
  4. data/README.md +44 -15
  5. data/app/assets/javascripts/plupload.settings.js.erb +4 -4
  6. data/lib/plupload/rails/version.rb +2 -3
  7. data/plupload-rails.gemspec +4 -3
  8. data/vendor/assets/images/jquery.plupload.queue/backgrounds.gif +0 -0
  9. data/vendor/assets/images/jquery.plupload.queue/buttons-disabled.png +0 -0
  10. data/vendor/assets/images/jquery.plupload.queue/buttons.png +0 -0
  11. data/vendor/assets/images/jquery.plupload.queue/delete.gif +0 -0
  12. data/vendor/assets/images/jquery.plupload.queue/done.gif +0 -0
  13. data/vendor/assets/images/jquery.plupload.queue/error.gif +0 -0
  14. data/vendor/assets/images/jquery.plupload.queue/throbber.gif +0 -0
  15. data/vendor/assets/images/jquery.plupload.queue/transp50.png +0 -0
  16. data/vendor/assets/images/jquery.ui.plupload/loading.gif +0 -0
  17. data/vendor/assets/images/jquery.ui.plupload/plupload.png +0 -0
  18. data/vendor/assets/javascripts/jquery.plupload.queue.js +414 -1
  19. data/vendor/assets/javascripts/jquery.ui.plupload.js +1216 -1
  20. data/vendor/assets/javascripts/moxie.js +10439 -0
  21. data/vendor/assets/javascripts/plupload.dev.js +2083 -0
  22. data/vendor/assets/javascripts/plupload/i18n/bs.js +1 -0
  23. data/vendor/assets/javascripts/plupload/i18n/cs.js +1 -14
  24. data/vendor/assets/javascripts/plupload/i18n/cy.js +1 -0
  25. data/vendor/assets/javascripts/plupload/i18n/da.js +1 -12
  26. data/vendor/assets/javascripts/plupload/i18n/de.js +1 -24
  27. data/vendor/assets/javascripts/plupload/i18n/el.js +1 -0
  28. data/vendor/assets/javascripts/plupload/i18n/en.js +1 -0
  29. data/vendor/assets/javascripts/plupload/i18n/es.js +1 -25
  30. data/vendor/assets/javascripts/plupload/i18n/et.js +1 -0
  31. data/vendor/assets/javascripts/plupload/i18n/fa.js +1 -0
  32. data/vendor/assets/javascripts/plupload/i18n/fi.js +1 -33
  33. data/vendor/assets/javascripts/plupload/i18n/fr.js +1 -25
  34. data/vendor/assets/javascripts/plupload/i18n/hr.js +1 -25
  35. data/vendor/assets/javascripts/plupload/i18n/hu.js +1 -33
  36. data/vendor/assets/javascripts/plupload/i18n/hy.js +1 -0
  37. data/vendor/assets/javascripts/plupload/i18n/it.js +1 -24
  38. data/vendor/assets/javascripts/plupload/i18n/ja.js +1 -37
  39. data/vendor/assets/javascripts/plupload/i18n/ka.js +1 -0
  40. data/vendor/assets/javascripts/plupload/i18n/ko.js +1 -0
  41. data/vendor/assets/javascripts/plupload/i18n/lt.js +1 -0
  42. data/vendor/assets/javascripts/plupload/i18n/lv.js +1 -33
  43. data/vendor/assets/javascripts/plupload/i18n/nl.js +1 -21
  44. data/vendor/assets/javascripts/plupload/i18n/pl.js +1 -24
  45. data/vendor/assets/javascripts/plupload/i18n/pt_BR.js +1 -0
  46. data/vendor/assets/javascripts/plupload/i18n/ro.js +1 -24
  47. data/vendor/assets/javascripts/plupload/i18n/ru.js +1 -21
  48. data/vendor/assets/javascripts/plupload/i18n/sk.js +1 -0
  49. data/vendor/assets/javascripts/plupload/i18n/sr.js +1 -14
  50. data/vendor/assets/javascripts/plupload/i18n/sv.js +1 -12
  51. data/vendor/assets/javascripts/plupload/i18n/th_TH.js +1 -0
  52. data/vendor/assets/javascripts/plupload/i18n/tr.js +1 -0
  53. data/vendor/assets/javascripts/plupload/i18n/uk_UA.js +1 -0
  54. data/vendor/assets/javascripts/plupload/i18n/zh_CN.js +1 -0
  55. data/vendor/assets/misc/Moxie.swf +0 -0
  56. data/vendor/assets/misc/Moxie.xap +0 -0
  57. data/vendor/assets/stylesheets/jquery.plupload.queue.scss +177 -177
  58. data/vendor/assets/stylesheets/jquery.ui.plupload.scss +362 -147
  59. metadata +42 -28
  60. data/vendor/assets/images/jquery.ui.plupload/plupload-bw.png +0 -0
  61. data/vendor/assets/javascripts/plupload.browserplus.js +0 -1
  62. data/vendor/assets/javascripts/plupload.flash.js +0 -1
  63. data/vendor/assets/javascripts/plupload.full.js +0 -2
  64. data/vendor/assets/javascripts/plupload.gears.js +0 -1
  65. data/vendor/assets/javascripts/plupload.html4.js +0 -1
  66. data/vendor/assets/javascripts/plupload.html5.js +0 -1
  67. data/vendor/assets/javascripts/plupload.js +0 -2
  68. data/vendor/assets/javascripts/plupload.silverlight.js +0 -1
  69. data/vendor/assets/javascripts/plupload/i18n/pt-br.js +0 -35
  70. data/vendor/assets/misc/plupload.flash.swf +0 -0
  71. data/vendor/assets/misc/plupload.silverlight.xap +0 -0
@@ -1 +1,414 @@
1
- (function(c){var d={};function a(e){return plupload.translate(e)||e}function b(f,e){e.contents().each(function(g,h){h=c(h);if(!h.is(".plupload")){h.remove()}});e.prepend('<div class="plupload_wrapper plupload_scroll"><div id="'+f+'_container" class="plupload_container"><div class="plupload"><div class="plupload_header"><div class="plupload_header_content"><div class="plupload_header_title">'+a("Select files")+'</div><div class="plupload_header_text">'+a("Add files to the upload queue and click the start button.")+'</div></div></div><div class="plupload_content"><div class="plupload_filelist_header"><div class="plupload_file_name">'+a("Filename")+'</div><div class="plupload_file_action">&nbsp;</div><div class="plupload_file_status"><span>'+a("Status")+'</span></div><div class="plupload_file_size">'+a("Size")+'</div><div class="plupload_clearer">&nbsp;</div></div><ul id="'+f+'_filelist" class="plupload_filelist"></ul><div class="plupload_filelist_footer"><div class="plupload_file_name"><div class="plupload_buttons"><a href="#" class="plupload_button plupload_add">'+a("Add files")+'</a><a href="#" class="plupload_button plupload_start">'+a("Start upload")+'</a></div><span class="plupload_upload_status"></span></div><div class="plupload_file_action"></div><div class="plupload_file_status"><span class="plupload_total_status">0%</span></div><div class="plupload_file_size"><span class="plupload_total_file_size">0 b</span></div><div class="plupload_progress"><div class="plupload_progress_container"><div class="plupload_progress_bar"></div></div></div><div class="plupload_clearer">&nbsp;</div></div></div></div></div><input type="hidden" id="'+f+'_count" name="'+f+'_count" value="0" /></div>')}c.fn.pluploadQueue=function(e){if(e){this.each(function(){var j,i,k;i=c(this);k=i.attr("id");if(!k){k=plupload.guid();i.attr("id",k)}j=new plupload.Uploader(c.extend({dragdrop:true,container:k},e));d[k]=j;function h(l){var n;if(l.status==plupload.DONE){n="plupload_done"}if(l.status==plupload.FAILED){n="plupload_failed"}if(l.status==plupload.QUEUED){n="plupload_delete"}if(l.status==plupload.UPLOADING){n="plupload_uploading"}var m=c("#"+l.id).attr("class",n).find("a").css("display","block");if(l.hint){m.attr("title",l.hint)}}function f(){c("span.plupload_total_status",i).html(j.total.percent+"%");c("div.plupload_progress_bar",i).css("width",j.total.percent+"%");c("span.plupload_upload_status",i).text(a("Uploaded %d/%d files").replace(/%d\/%d/,j.total.uploaded+"/"+j.files.length))}function g(){var m=c("ul.plupload_filelist",i).html(""),n=0,l;c.each(j.files,function(p,o){l="";if(o.status==plupload.DONE){if(o.target_name){l+='<input type="hidden" name="'+k+"_"+n+'_tmpname" value="'+plupload.xmlEncode(o.target_name)+'" />'}l+='<input type="hidden" name="'+k+"_"+n+'_name" value="'+plupload.xmlEncode(o.name)+'" />';l+='<input type="hidden" name="'+k+"_"+n+'_status" value="'+(o.status==plupload.DONE?"done":"failed")+'" />';n++;c("#"+k+"_count").val(n)}m.append('<li id="'+o.id+'"><div class="plupload_file_name"><span>'+o.name+'</span></div><div class="plupload_file_action"><a href="#"></a></div><div class="plupload_file_status">'+o.percent+'%</div><div class="plupload_file_size">'+plupload.formatSize(o.size)+'</div><div class="plupload_clearer">&nbsp;</div>'+l+"</li>");h(o);c("#"+o.id+".plupload_delete a").click(function(q){c("#"+o.id).remove();j.removeFile(o);q.preventDefault()})});c("span.plupload_total_file_size",i).html(plupload.formatSize(j.total.size));if(j.total.queued===0){c("span.plupload_add_text",i).text(a("Add files."))}else{c("span.plupload_add_text",i).text(j.total.queued+" files queued.")}c("a.plupload_start",i).toggleClass("plupload_disabled",j.files.length==(j.total.uploaded+j.total.failed));m[0].scrollTop=m[0].scrollHeight;f();if(!j.files.length&&j.features.dragdrop&&j.settings.dragdrop){c("#"+k+"_filelist").append('<li class="plupload_droptext">'+a("Drag files here.")+"</li>")}}j.bind("UploadFile",function(l,m){c("#"+m.id).addClass("plupload_current_file")});j.bind("Init",function(l,m){b(k,i);if(!e.unique_names&&e.rename){c("#"+k+"_filelist div.plupload_file_name span",i).live("click",function(s){var q=c(s.target),o,r,n,p="";o=l.getFile(q.parents("li")[0].id);n=o.name;r=/^(.+)(\.[^.]+)$/.exec(n);if(r){n=r[1];p=r[2]}q.hide().after('<input type="text" />');q.next().val(n).focus().blur(function(){q.show().next().remove()}).keydown(function(u){var t=c(this);if(u.keyCode==13){u.preventDefault();o.name=t.val()+p;q.text(o.name);t.blur()}})})}c("a.plupload_add",i).attr("id",k+"_browse");l.settings.browse_button=k+"_browse";if(l.features.dragdrop&&l.settings.dragdrop){l.settings.drop_element=k+"_filelist";c("#"+k+"_filelist").append('<li class="plupload_droptext">'+a("Drag files here.")+"</li>")}c("#"+k+"_container").attr("title","Using runtime: "+m.runtime);c("a.plupload_start",i).click(function(n){if(!c(this).hasClass("plupload_disabled")){j.start()}n.preventDefault()});c("a.plupload_stop",i).click(function(n){n.preventDefault();j.stop()});c("a.plupload_start",i).addClass("plupload_disabled")});j.init();j.bind("Error",function(l,o){var m=o.file,n;if(m){n=o.message;if(o.details){n+=" ("+o.details+")"}if(o.code==plupload.FILE_SIZE_ERROR){alert(a("Error: File too large: ")+m.name)}if(o.code==plupload.FILE_EXTENSION_ERROR){alert(a("Error: Invalid file extension: ")+m.name)}m.hint=n;c("#"+m.id).attr("class","plupload_failed").find("a").css("display","block").attr("title",n)}});j.bind("StateChanged",function(){if(j.state===plupload.STARTED){c("li.plupload_delete a,div.plupload_buttons",i).hide();c("span.plupload_upload_status,div.plupload_progress,a.plupload_stop",i).css("display","block");c("span.plupload_upload_status",i).text("Uploaded "+j.total.uploaded+"/"+j.files.length+" files");if(e.multiple_queues){c("span.plupload_total_status,span.plupload_total_file_size",i).show()}}else{g();c("a.plupload_stop,div.plupload_progress",i).hide();c("a.plupload_delete",i).css("display","block")}});j.bind("QueueChanged",g);j.bind("FileUploaded",function(l,m){h(m)});j.bind("UploadProgress",function(l,m){c("#"+m.id+" div.plupload_file_status",i).html(m.percent+"%");h(m);f();if(e.multiple_queues&&j.total.uploaded+j.total.failed==j.files.length){c(".plupload_buttons,.plupload_upload_status",i).css("display","inline");c(".plupload_start",i).addClass("plupload_disabled");c("span.plupload_total_status,span.plupload_total_file_size",i).hide()}});if(e.setup){e.setup(j)}});return this}else{return d[c(this[0]).attr("id")]}}})(jQuery);
1
+ /**
2
+ * jquery.plupload.queue.js
3
+ *
4
+ * Copyright 2009, Moxiecode Systems AB
5
+ * Released under GPL License.
6
+ *
7
+ * License: http://www.plupload.com/license
8
+ * Contributing: http://www.plupload.com/contributing
9
+ */
10
+
11
+ /* global jQuery:true, alert:true */
12
+
13
+ /**
14
+ jQuery based implementation of the Plupload API - multi-runtime file uploading API.
15
+
16
+ To use the widget you must include _jQuery_. It is not meant to be extended in any way and is provided to be
17
+ used as it is.
18
+
19
+ @example
20
+ <!-- Instantiating: -->
21
+ <div id="uploader">
22
+ <p>Your browser doesn't have Flash, Silverlight or HTML5 support.</p>
23
+ </div>
24
+
25
+ <script>
26
+ $('#uploader').pluploadQueue({
27
+ url : '../upload.php',
28
+ filters : [
29
+ {title : "Image files", extensions : "jpg,gif,png"}
30
+ ],
31
+ rename: true,
32
+ flash_swf_url : '../../js/Moxie.swf',
33
+ silverlight_xap_url : '../../js/Moxie.xap',
34
+ });
35
+ </script>
36
+
37
+ @example
38
+ // Retrieving a reference to plupload.Uploader object
39
+ var uploader = $('#uploader').pluploadQueue();
40
+
41
+ uploader.bind('FilesAdded', function() {
42
+
43
+ // Autostart
44
+ setTimeout(uploader.start, 1); // "detach" from the main thread
45
+ });
46
+
47
+ @class pluploadQueue
48
+ @constructor
49
+ @param {Object} settings For detailed information about each option check documentation.
50
+ @param {String} settings.url URL of the server-side upload handler.
51
+ @param {Number|String} [settings.chunk_size=0] Chunk size in bytes to slice the file into. Shorcuts with b, kb, mb, gb, tb suffixes also supported. `e.g. 204800 or "204800b" or "200kb"`. By default - disabled.
52
+ @param {String} [settings.file_data_name="file"] Name for the file field in Multipart formated message.
53
+ @param {Array} [settings.filters=[]] Set of file type filters, each one defined by hash of title and extensions. `e.g. {title : "Image files", extensions : "jpg,jpeg,gif,png"}`. Dispatches `plupload.FILE_EXTENSION_ERROR`
54
+ @param {String} [settings.flash_swf_url] URL of the Flash swf.
55
+ @param {Object} [settings.headers] Custom headers to send with the upload. Hash of name/value pairs.
56
+ @param {Number|String} [settings.max_file_size] Maximum file size that the user can pick, in bytes. Optionally supports b, kb, mb, gb, tb suffixes. `e.g. "10mb" or "1gb"`. By default - not set. Dispatches `plupload.FILE_SIZE_ERROR`.
57
+ @param {Number} [settings.max_retries=0] How many times to retry the chunk or file, before triggering Error event.
58
+ @param {Boolean} [settings.multipart=true] Whether to send file and additional parameters as Multipart formated message.
59
+ @param {Object} [settings.multipart_params] Hash of key/value pairs to send with every file upload.
60
+ @param {Boolean} [settings.multi_selection=true] Enable ability to select multiple files at once in file dialog.
61
+ @param {Boolean} [settings.prevent_duplicates=false] Do not let duplicates into the queue. Dispatches `plupload.FILE_DUPLICATE_ERROR`.
62
+ @param {String|Object} [settings.required_features] Either comma-separated list or hash of required features that chosen runtime should absolutely possess.
63
+ @param {Object} [settings.resize] Enable resizng of images on client-side. Applies to `image/jpeg` and `image/png` only. `e.g. {width : 200, height : 200, quality : 90, crop: true}`
64
+ @param {Number} [settings.resize.width] If image is bigger, it will be resized.
65
+ @param {Number} [settings.resize.height] If image is bigger, it will be resized.
66
+ @param {Number} [settings.resize.quality=90] Compression quality for jpegs (1-100).
67
+ @param {Boolean} [settings.resize.crop=false] Whether to crop images to exact dimensions. By default they will be resized proportionally.
68
+ @param {String} [settings.runtimes="html5,flash,silverlight,html4"] Comma separated list of runtimes, that Plupload will try in turn, moving to the next if previous fails.
69
+ @param {String} [settings.silverlight_xap_url] URL of the Silverlight xap.
70
+ @param {Boolean} [settings.unique_names=false] If true will generate unique filenames for uploaded files.
71
+
72
+ @param {Boolean} [settings.dragdrop=true] Enable ability to add file to the queue by drag'n'dropping them from the desktop.
73
+ @param {Boolean} [settings.rename=false] Enable ability to rename files in the queue.
74
+ @param {Boolean} [settings.multiple_queues=true] Re-activate the widget after each upload procedure.
75
+ */
76
+ (function($) {
77
+ var uploaders = {};
78
+
79
+ function _(str) {
80
+ return plupload.translate(str) || str;
81
+ }
82
+
83
+ function renderUI(id, target) {
84
+ // Remove all existing non plupload items
85
+ target.contents().each(function(i, node) {
86
+ node = $(node);
87
+
88
+ if (!node.is('.plupload')) {
89
+ node.remove();
90
+ }
91
+ });
92
+
93
+ target.prepend(
94
+ '<div class="plupload_wrapper plupload_scroll">' +
95
+ '<div id="' + id + '_container" class="plupload_container">' +
96
+ '<div class="plupload">' +
97
+ '<div class="plupload_header">' +
98
+ '<div class="plupload_header_content">' +
99
+ '<div class="plupload_header_title">' + _('Select files') + '</div>' +
100
+ '<div class="plupload_header_text">' + _('Add files to the upload queue and click the start button.') + '</div>' +
101
+ '</div>' +
102
+ '</div>' +
103
+
104
+ '<div class="plupload_content">' +
105
+ '<div class="plupload_filelist_header">' +
106
+ '<div class="plupload_file_name">' + _('Filename') + '</div>' +
107
+ '<div class="plupload_file_action">&nbsp;</div>' +
108
+ '<div class="plupload_file_status"><span>' + _('Status') + '</span></div>' +
109
+ '<div class="plupload_file_size">' + _('Size') + '</div>' +
110
+ '<div class="plupload_clearer">&nbsp;</div>' +
111
+ '</div>' +
112
+
113
+ '<ul id="' + id + '_filelist" class="plupload_filelist"></ul>' +
114
+
115
+ '<div class="plupload_filelist_footer">' +
116
+ '<div class="plupload_file_name">' +
117
+ '<div class="plupload_buttons">' +
118
+ '<a href="#" class="plupload_button plupload_add" id="' + id + '_browse">' + _('Add Files') + '</a>' +
119
+ '<a href="#" class="plupload_button plupload_start">' + _('Start Upload') + '</a>' +
120
+ '</div>' +
121
+ '<span class="plupload_upload_status"></span>' +
122
+ '</div>' +
123
+ '<div class="plupload_file_action"></div>' +
124
+ '<div class="plupload_file_status"><span class="plupload_total_status">0%</span></div>' +
125
+ '<div class="plupload_file_size"><span class="plupload_total_file_size">0 b</span></div>' +
126
+ '<div class="plupload_progress">' +
127
+ '<div class="plupload_progress_container">' +
128
+ '<div class="plupload_progress_bar"></div>' +
129
+ '</div>' +
130
+ '</div>' +
131
+ '<div class="plupload_clearer">&nbsp;</div>' +
132
+ '</div>' +
133
+ '</div>' +
134
+ '</div>' +
135
+ '</div>' +
136
+ '<input type="hidden" id="' + id + '_count" name="' + id + '_count" value="0" />' +
137
+ '</div>'
138
+ );
139
+ }
140
+
141
+ $.fn.pluploadQueue = function(settings) {
142
+ if (settings) {
143
+ this.each(function() {
144
+ var uploader, target, id, contents_bak;
145
+
146
+ target = $(this);
147
+ id = target.attr('id');
148
+
149
+ if (!id) {
150
+ id = plupload.guid();
151
+ target.attr('id', id);
152
+ }
153
+
154
+ contents_bak = target.html();
155
+ renderUI(id, target);
156
+
157
+ uploader = new plupload.Uploader($.extend({
158
+ dragdrop : true,
159
+ browse_button : id + '_browse',
160
+ container : id
161
+ }, settings));
162
+
163
+ uploaders[id] = uploader;
164
+
165
+ function handleStatus(file) {
166
+ var actionClass;
167
+
168
+ if (file.status == plupload.DONE) {
169
+ actionClass = 'plupload_done';
170
+ }
171
+
172
+ if (file.status == plupload.FAILED) {
173
+ actionClass = 'plupload_failed';
174
+ }
175
+
176
+ if (file.status == plupload.QUEUED) {
177
+ actionClass = 'plupload_delete';
178
+ }
179
+
180
+ if (file.status == plupload.UPLOADING) {
181
+ actionClass = 'plupload_uploading';
182
+ }
183
+
184
+ var icon = $('#' + file.id).attr('class', actionClass).find('a').css('display', 'block');
185
+ if (file.hint) {
186
+ icon.attr('title', file.hint);
187
+ }
188
+ }
189
+
190
+ function updateTotalProgress() {
191
+ $('span.plupload_total_status', target).html(uploader.total.percent + '%');
192
+ $('div.plupload_progress_bar', target).css('width', uploader.total.percent + '%');
193
+ $('span.plupload_upload_status', target).html(
194
+ _('Uploaded %d/%d files').replace(/%d\/%d/, uploader.total.uploaded+'/'+uploader.files.length)
195
+ );
196
+ }
197
+
198
+ function updateList() {
199
+ var fileList = $('ul.plupload_filelist', target).html(''), inputCount = 0, inputHTML;
200
+
201
+ $.each(uploader.files, function(i, file) {
202
+ inputHTML = '';
203
+
204
+ if (file.status == plupload.DONE) {
205
+ if (file.target_name) {
206
+ inputHTML += '<input type="hidden" name="' + id + '_' + inputCount + '_tmpname" value="' + plupload.xmlEncode(file.target_name) + '" />';
207
+ }
208
+
209
+ inputHTML += '<input type="hidden" name="' + id + '_' + inputCount + '_name" value="' + plupload.xmlEncode(file.name) + '" />';
210
+ inputHTML += '<input type="hidden" name="' + id + '_' + inputCount + '_status" value="' + (file.status == plupload.DONE ? 'done' : 'failed') + '" />';
211
+
212
+ inputCount++;
213
+
214
+ $('#' + id + '_count').val(inputCount);
215
+ }
216
+
217
+ fileList.append(
218
+ '<li id="' + file.id + '">' +
219
+ '<div class="plupload_file_name"><span>' + file.name + '</span></div>' +
220
+ '<div class="plupload_file_action"><a href="#"></a></div>' +
221
+ '<div class="plupload_file_status">' + file.percent + '%</div>' +
222
+ '<div class="plupload_file_size">' + plupload.formatSize(file.size) + '</div>' +
223
+ '<div class="plupload_clearer">&nbsp;</div>' +
224
+ inputHTML +
225
+ '</li>'
226
+ );
227
+
228
+ handleStatus(file);
229
+
230
+ $('#' + file.id + '.plupload_delete a').click(function(e) {
231
+ $('#' + file.id).remove();
232
+ uploader.removeFile(file);
233
+
234
+ e.preventDefault();
235
+ });
236
+ });
237
+
238
+ $('span.plupload_total_file_size', target).html(plupload.formatSize(uploader.total.size));
239
+
240
+ if (uploader.total.queued === 0) {
241
+ $('span.plupload_add_text', target).html(_('Add Files'));
242
+ } else {
243
+ $('span.plupload_add_text', target).html(_('%d files queued').replace(/%d/, uploader.total.queued));
244
+ }
245
+
246
+ $('a.plupload_start', target).toggleClass('plupload_disabled', uploader.files.length == (uploader.total.uploaded + uploader.total.failed));
247
+
248
+ // Scroll to end of file list
249
+ fileList[0].scrollTop = fileList[0].scrollHeight;
250
+
251
+ updateTotalProgress();
252
+
253
+ // Re-add drag message if there is no files
254
+ if (!uploader.files.length && uploader.features.dragdrop && uploader.settings.dragdrop) {
255
+ $('#' + id + '_filelist').append('<li class="plupload_droptext">' + _("Drag files here.") + '</li>');
256
+ }
257
+ }
258
+
259
+ function destroy() {
260
+ delete uploaders[id];
261
+ uploader.destroy();
262
+ target.html(contents_bak);
263
+ uploader = target = contents_bak = null;
264
+ }
265
+
266
+ uploader.bind("UploadFile", function(up, file) {
267
+ $('#' + file.id).addClass('plupload_current_file');
268
+ });
269
+
270
+ uploader.bind('Init', function(up, res) {
271
+ // Enable rename support
272
+ if (!settings.unique_names && settings.rename) {
273
+ target.on('click', '#' + id + '_filelist div.plupload_file_name span', function(e) {
274
+ var targetSpan = $(e.target), file, parts, name, ext = "";
275
+
276
+ // Get file name and split out name and extension
277
+ file = up.getFile(targetSpan.parents('li')[0].id);
278
+ name = file.name;
279
+ parts = /^(.+)(\.[^.]+)$/.exec(name);
280
+ if (parts) {
281
+ name = parts[1];
282
+ ext = parts[2];
283
+ }
284
+
285
+ // Display input element
286
+ targetSpan.hide().after('<input type="text" />');
287
+ targetSpan.next().val(name).focus().blur(function() {
288
+ targetSpan.show().next().remove();
289
+ }).keydown(function(e) {
290
+ var targetInput = $(this);
291
+
292
+ if (e.keyCode == 13) {
293
+ e.preventDefault();
294
+
295
+ // Rename file and glue extension back on
296
+ file.name = targetInput.val() + ext;
297
+ targetSpan.html(file.name);
298
+ targetInput.blur();
299
+ }
300
+ });
301
+ });
302
+ }
303
+
304
+
305
+ // Enable drag/drop (see PostInit handler as well)
306
+ if (up.settings.dragdrop) {
307
+ up.settings.drop_element = id + '_filelist';
308
+ }
309
+
310
+ $('#' + id + '_container').attr('title', 'Using runtime: ' + res.runtime);
311
+
312
+ $('a.plupload_start', target).click(function(e) {
313
+ if (!$(this).hasClass('plupload_disabled')) {
314
+ uploader.start();
315
+ }
316
+
317
+ e.preventDefault();
318
+ });
319
+
320
+ $('a.plupload_stop', target).click(function(e) {
321
+ e.preventDefault();
322
+ uploader.stop();
323
+ });
324
+
325
+ $('a.plupload_start', target).addClass('plupload_disabled');
326
+ });
327
+
328
+ uploader.bind("Error", function(up, err) {
329
+ var file = err.file, message;
330
+
331
+ if (file) {
332
+ message = err.message;
333
+
334
+ if (err.details) {
335
+ message += " (" + err.details + ")";
336
+ }
337
+
338
+ if (err.code == plupload.FILE_SIZE_ERROR) {
339
+ alert(_("Error: File too large:") + " " + file.name);
340
+ }
341
+
342
+ if (err.code == plupload.FILE_EXTENSION_ERROR) {
343
+ alert(_("Error: Invalid file extension:") + " " + file.name);
344
+ }
345
+
346
+ file.hint = message;
347
+ $('#' + file.id).attr('class', 'plupload_failed').find('a').css('display', 'block').attr('title', message);
348
+ }
349
+
350
+ if (err.code === plupload.INIT_ERROR) {
351
+ setTimeout(function() {
352
+ destroy();
353
+ }, 1);
354
+ }
355
+ });
356
+
357
+ uploader.bind("PostInit", function(up) {
358
+ // features are populated only after input components are fully instantiated
359
+ if (up.settings.dragdrop && up.features.dragdrop) {
360
+ $('#' + id + '_filelist').append('<li class="plupload_droptext">' + _("Drag files here.") + '</li>');
361
+ }
362
+ });
363
+
364
+ uploader.init();
365
+
366
+ uploader.bind('StateChanged', function() {
367
+ if (uploader.state === plupload.STARTED) {
368
+ $('li.plupload_delete a,div.plupload_buttons', target).hide();
369
+ $('span.plupload_upload_status,div.plupload_progress,a.plupload_stop', target).css('display', 'block');
370
+ $('span.plupload_upload_status', target).html('Uploaded ' + uploader.total.uploaded + '/' + uploader.files.length + ' files');
371
+
372
+ if (settings.multiple_queues) {
373
+ $('span.plupload_total_status,span.plupload_total_file_size', target).show();
374
+ }
375
+ } else {
376
+ updateList();
377
+ $('a.plupload_stop,div.plupload_progress', target).hide();
378
+ $('a.plupload_delete', target).css('display', 'block');
379
+
380
+ if (settings.multiple_queues && uploader.total.uploaded + uploader.total.failed == uploader.files.length) {
381
+ $(".plupload_buttons,.plupload_upload_status", target).css("display", "inline");
382
+ $(".plupload_start", target).addClass("plupload_disabled");
383
+ $('span.plupload_total_status,span.plupload_total_file_size', target).hide();
384
+ }
385
+ }
386
+ });
387
+
388
+ uploader.bind('QueueChanged', updateList);
389
+
390
+ uploader.bind('FileUploaded', function(up, file) {
391
+ handleStatus(file);
392
+ });
393
+
394
+ uploader.bind("UploadProgress", function(up, file) {
395
+ // Set file specific progress
396
+ $('#' + file.id + ' div.plupload_file_status', target).html(file.percent + '%');
397
+
398
+ handleStatus(file);
399
+ updateTotalProgress();
400
+ });
401
+
402
+ // Call setup function
403
+ if (settings.setup) {
404
+ settings.setup(uploader);
405
+ }
406
+ });
407
+
408
+ return this;
409
+ } else {
410
+ // Get uploader instance for specified element
411
+ return uploaders[$(this[0]).attr('id')];
412
+ }
413
+ };
414
+ })(jQuery);
@@ -1 +1,1216 @@
1
- (function(f,a,c,g,e){var h={};function b(i){return c.translate(i)||i}function d(i){i.html('<div class="plupload_wrapper"><div class="ui-widget-content plupload_container"><div class="plupload"><div class="ui-state-default ui-widget-header plupload_header"><div class="plupload_header_content"><div class="plupload_header_title">'+b("Select files")+'</div><div class="plupload_header_text">'+b("Add files to the upload queue and click the start button.")+'</div></div></div><div class="plupload_content"><table class="plupload_filelist"><tr class="ui-widget-header plupload_filelist_header"><td class="plupload_cell plupload_file_name">'+b("Filename")+'</td><td class="plupload_cell plupload_file_status">'+b("Status")+'</td><td class="plupload_cell plupload_file_size">'+b("Size")+'</td><td class="plupload_cell plupload_file_action">&nbsp;</td></tr></table><div class="plupload_scroll"><table class="plupload_filelist_content"></table></div><table class="plupload_filelist"><tr class="ui-widget-header ui-widget-content plupload_filelist_footer"><td class="plupload_cell plupload_file_name"><div class="plupload_buttons"><!-- Visible --><a class="plupload_button plupload_add">'+b("Add Files")+'</a>&nbsp;<a class="plupload_button plupload_start">'+b("Start Upload")+'</a>&nbsp;<a class="plupload_button plupload_stop plupload_hidden">'+b("Stop Upload")+'</a>&nbsp;</div><div class="plupload_started plupload_hidden"><!-- Hidden --><div class="plupload_progress plupload_right"><div class="plupload_progress_container"></div></div><div class="plupload_cell plupload_upload_status"></div><div class="plupload_clearer">&nbsp;</div></div></td><td class="plupload_file_status"><span class="plupload_total_status">0%</span></td><td class="plupload_file_size"><span class="plupload_total_file_size">0 kb</span></td><td class="plupload_file_action"></td></tr></table></div></div></div><input class="plupload_count" value="0" type="hidden"></div>')}g.widget("ui.plupload",{contents_bak:"",runtime:null,options:{browse_button_hover:"ui-state-hover",browse_button_active:"ui-state-active",dragdrop:true,multiple_queues:true,buttons:{browse:true,start:true,stop:true},autostart:false,sortable:false,rename:false,max_file_count:0},FILE_COUNT_ERROR:-9001,_create:function(){var i=this,k,j;k=this.element.attr("id");if(!k){k=c.guid();this.element.attr("id",k)}this.id=k;this.contents_bak=this.element.html();d(this.element);this.container=g(".plupload_container",this.element).attr("id",k+"_container");this.filelist=g(".plupload_filelist_content",this.container).attr({id:k+"_filelist",unselectable:"on"});this.browse_button=g(".plupload_add",this.container).attr("id",k+"_browse");this.start_button=g(".plupload_start",this.container).attr("id",k+"_start");this.stop_button=g(".plupload_stop",this.container).attr("id",k+"_stop");if(g.ui.button){this.browse_button.button({icons:{primary:"ui-icon-circle-plus"}});this.start_button.button({icons:{primary:"ui-icon-circle-arrow-e"},disabled:true});this.stop_button.button({icons:{primary:"ui-icon-circle-close"}})}this.progressbar=g(".plupload_progress_container",this.container);if(g.ui.progressbar){this.progressbar.progressbar()}this.counter=g(".plupload_count",this.element).attr({id:k+"_count",name:k+"_count"});j=this.uploader=h[k]=new c.Uploader(g.extend({container:k,browse_button:k+"_browse"},this.options));j.bind("Error",function(l,m){if(m.code===c.INIT_ERROR){i.destroy()}});j.bind("Init",function(l,m){if(!i.options.buttons.browse){i.browse_button.button("disable").hide();l.disableBrowse(true)}if(!i.options.buttons.start){i.start_button.button("disable").hide()}if(!i.options.buttons.stop){i.stop_button.button("disable").hide()}if(!i.options.unique_names&&i.options.rename){i._enableRenaming()}if(j.features.dragdrop&&i.options.dragdrop){i._enableDragAndDrop()}i.container.attr("title",b("Using runtime: ")+(i.runtime=m.runtime));i.start_button.click(function(n){if(!g(this).button("option","disabled")){i.start()}n.preventDefault()});i.stop_button.click(function(n){i.stop();n.preventDefault()})});if(i.options.max_file_count){j.bind("FilesAdded",function(l,n){var o=[],m=n.length;var p=l.files.length+m-i.options.max_file_count;if(p>0){o=n.splice(m-p,p);l.trigger("Error",{code:i.FILE_COUNT_ERROR,message:b("File count error."),file:o})}})}j.init();j.bind("FilesAdded",function(l,m){i._trigger("selected",null,{up:l,files:m});if(i.options.autostart){setTimeout(function(){i.start()},10)}});j.bind("FilesRemoved",function(l,m){i._trigger("removed",null,{up:l,files:m})});j.bind("QueueChanged",function(){i._updateFileList()});j.bind("StateChanged",function(){i._handleState()});j.bind("UploadFile",function(l,m){i._handleFileStatus(m)});j.bind("FileUploaded",function(l,m){i._handleFileStatus(m);i._trigger("uploaded",null,{up:l,file:m})});j.bind("UploadProgress",function(l,m){g("#"+m.id).find(".plupload_file_status").html(m.percent+"%").end().find(".plupload_file_size").html(c.formatSize(m.size));i._handleFileStatus(m);i._updateTotalProgress();i._trigger("progress",null,{up:l,file:m})});j.bind("UploadComplete",function(l,m){i._trigger("complete",null,{up:l,files:m})});j.bind("Error",function(l,p){var n=p.file,o,m;if(n){o="<strong>"+p.message+"</strong>";m=p.details;if(m){o+=" <br /><i>"+p.details+"</i>"}else{switch(p.code){case c.FILE_EXTENSION_ERROR:m=b("File: %s").replace("%s",n.name);break;case c.FILE_SIZE_ERROR:m=b("File: %f, size: %s, max file size: %m").replace(/%([fsm])/g,function(r,q){switch(q){case"f":return n.name;case"s":return n.size;case"m":return c.parseSize(i.options.max_file_size)}});break;case i.FILE_COUNT_ERROR:m=b("Upload element accepts only %d file(s) at a time. Extra files were stripped.").replace("%d",i.options.max_file_count);break;case c.IMAGE_FORMAT_ERROR:m=c.translate("Image format either wrong or not supported.");break;case c.IMAGE_MEMORY_ERROR:m=c.translate("Runtime ran out of available memory.");break;case c.IMAGE_DIMENSIONS_ERROR:m=c.translate("Resoultion out of boundaries! <b>%s</b> runtime supports images only up to %wx%hpx.").replace(/%([swh])/g,function(r,q){switch(q){case"s":return l.runtime;case"w":return l.features.maxWidth;case"h":return l.features.maxHeight}});break;case c.HTTP_ERROR:m=b("Upload URL might be wrong or doesn't exist");break}o+=" <br /><i>"+m+"</i>"}i.notify("error",o);i._trigger("error",null,{up:l,file:n,error:o})}})},_setOption:function(j,k){var i=this;if(j=="buttons"&&typeof(k)=="object"){k=g.extend(i.options.buttons,k);if(!k.browse){i.browse_button.button("disable").hide();up.disableBrowse(true)}else{i.browse_button.button("enable").show();up.disableBrowse(false)}if(!k.start){i.start_button.button("disable").hide()}else{i.start_button.button("enable").show()}if(!k.stop){i.stop_button.button("disable").hide()}else{i.start_button.button("enable").show()}}i.uploader.settings[j]=k},start:function(){this.uploader.start();this._trigger("start",null)},stop:function(){this.uploader.stop();this._trigger("stop",null)},getFile:function(j){var i;if(typeof j==="number"){i=this.uploader.files[j]}else{i=this.uploader.getFile(j)}return i},removeFile:function(j){var i=this.getFile(j);if(i){this.uploader.removeFile(i)}},clearQueue:function(){this.uploader.splice()},getUploader:function(){return this.uploader},refresh:function(){this.uploader.refresh()},_handleState:function(){var j=this,i=this.uploader;if(i.state===c.STARTED){g(j.start_button).button("disable");g([]).add(j.stop_button).add(".plupload_started").removeClass("plupload_hidden");g(".plupload_upload_status",j.element).text(b("Uploaded %d/%d files").replace("%d/%d",i.total.uploaded+"/"+i.files.length));g(".plupload_header_content",j.element).addClass("plupload_header_content_bw")}else{g([]).add(j.stop_button).add(".plupload_started").addClass("plupload_hidden");if(j.options.multiple_queues){g(j.start_button).button("enable");g(".plupload_header_content",j.element).removeClass("plupload_header_content_bw")}j._updateFileList()}},_handleFileStatus:function(l){var n,j;if(!g("#"+l.id).length){return}switch(l.status){case c.DONE:n="plupload_done";j="ui-icon ui-icon-circle-check";break;case c.FAILED:n="ui-state-error plupload_failed";j="ui-icon ui-icon-alert";break;case c.QUEUED:n="plupload_delete";j="ui-icon ui-icon-circle-minus";break;case c.UPLOADING:n="ui-state-highlight plupload_uploading";j="ui-icon ui-icon-circle-arrow-w";var i=g(".plupload_scroll",this.container),m=i.scrollTop(),o=i.height(),k=g("#"+l.id).position().top+g("#"+l.id).height();if(o<k){i.scrollTop(m+k-o)}break}n+=" ui-state-default plupload_file";g("#"+l.id).attr("class",n).find(".ui-icon").attr("class",j)},_updateTotalProgress:function(){var i=this.uploader;this.progressbar.progressbar("value",i.total.percent);this.element.find(".plupload_total_status").html(i.total.percent+"%").end().find(".plupload_total_file_size").html(c.formatSize(i.total.size)).end().find(".plupload_upload_status").text(b("Uploaded %d/%d files").replace("%d/%d",i.total.uploaded+"/"+i.files.length))},_updateFileList:function(){var k=this,j=this.uploader,m=this.filelist,l=0,o,n=this.id+"_",i;if(g.ui.sortable&&this.options.sortable){g("tbody",m).sortable("destroy")}m.empty();g.each(j.files,function(q,p){i="";o=n+l;if(p.status===c.DONE){if(p.target_name){i+='<input type="hidden" name="'+o+'_tmpname" value="'+c.xmlEncode(p.target_name)+'" />'}i+='<input type="hidden" name="'+o+'_name" value="'+c.xmlEncode(p.name)+'" />';i+='<input type="hidden" name="'+o+'_status" value="'+(p.status===c.DONE?"done":"failed")+'" />';l++;k.counter.val(l)}m.append('<tr class="ui-state-default plupload_file" id="'+p.id+'"><td class="plupload_cell plupload_file_name"><span>'+p.name+'</span></td><td class="plupload_cell plupload_file_status">'+p.percent+'%</td><td class="plupload_cell plupload_file_size">'+c.formatSize(p.size)+'</td><td class="plupload_cell plupload_file_action"><div class="ui-icon"></div>'+i+"</td></tr>");k._handleFileStatus(p);g("#"+p.id+".plupload_delete .ui-icon, #"+p.id+".plupload_done .ui-icon").click(function(r){g("#"+p.id).remove();j.removeFile(p);r.preventDefault()});k._trigger("updatelist",null,m)});if(j.total.queued===0){g(".ui-button-text",k.browse_button).text(b("Add Files"))}else{g(".ui-button-text",k.browse_button).text(b("%d files queued").replace("%d",j.total.queued))}if(j.files.length===(j.total.uploaded+j.total.failed)){k.start_button.button("disable")}else{k.start_button.button("enable")}m[0].scrollTop=m[0].scrollHeight;k._updateTotalProgress();if(!j.files.length&&j.features.dragdrop&&j.settings.dragdrop){g("#"+o+"_filelist").append('<tr><td class="plupload_droptext">'+b("Drag files here.")+"</td></tr>")}else{if(k.options.sortable&&g.ui.sortable){k._enableSortingList()}}},_enableRenaming:function(){var i=this;g(".plupload_delete .plupload_file_name span",this.filelist).live("click",function(o){var m=g(o.target),k,n,j,l="";k=i.uploader.getFile(m.parents("tr")[0].id);j=k.name;n=/^(.+)(\.[^.]+)$/.exec(j);if(n){j=n[1];l=n[2]}m.hide().after('<input class="plupload_file_rename" type="text" />');m.next().val(j).focus().blur(function(){m.show().next().remove()}).keydown(function(q){var p=g(this);if(g.inArray(q.keyCode,[13,27])!==-1){q.preventDefault();if(q.keyCode===13){k.name=p.val()+l;m.text(k.name)}p.blur()}})})},_enableDragAndDrop:function(){this.filelist.append('<tr><td class="plupload_droptext">'+b("Drag files here.")+"</td></tr>");this.filelist.parent().attr("id",this.id+"_dropbox");this.uploader.settings.drop_element=this.options.drop_element=this.id+"_dropbox"},_enableSortingList:function(){var j,i=this;if(g("tbody tr",this.filelist).length<2){return}g("tbody",this.filelist).sortable({containment:"parent",items:".plupload_delete",helper:function(l,k){return k.clone(true).find("td:not(.plupload_file_name)").remove().end().css("width","100%")},stop:function(p,o){var l,n,k,m=[];g.each(g(this).sortable("toArray"),function(q,r){m[m.length]=i.uploader.getFile(r)});m.unshift(m.length);m.unshift(0);Array.prototype.splice.apply(i.uploader.files,m)}})},notify:function(j,k){var i=g('<div class="plupload_message"><span class="plupload_message_close ui-icon ui-icon-circle-close" title="'+b("Close")+'"></span><p><span class="ui-icon"></span>'+k+"</p></div>");i.addClass("ui-state-"+(j==="error"?"error":"highlight")).find("p .ui-icon").addClass("ui-icon-"+(j==="error"?"alert":"info")).end().find(".plupload_message_close").click(function(){i.remove()}).end();g(".plupload_header_content",this.container).append(i)},destroy:function(){g(".plupload_button",this.element).unbind();if(g.ui.button){g(".plupload_add, .plupload_start, .plupload_stop",this.container).button("destroy")}if(g.ui.progressbar){this.progressbar.progressbar("destroy")}if(g.ui.sortable&&this.options.sortable){g("tbody",this.filelist).sortable("destroy")}this.uploader.destroy();this.element.empty().html(this.contents_bak);this.contents_bak="";g.Widget.prototype.destroy.apply(this)}})}(window,document,plupload,jQuery));
1
+ /**
2
+ * jquery.ui.plupload.js
3
+ *
4
+ * Copyright 2013, Moxiecode Systems AB
5
+ * Released under GPL License.
6
+ *
7
+ * License: http://www.plupload.com/license
8
+ * Contributing: http://www.plupload.com/contributing
9
+ *
10
+ * Depends:
11
+ * jquery.ui.core.js
12
+ * jquery.ui.widget.js
13
+ * jquery.ui.button.js
14
+ * jquery.ui.progressbar.js
15
+ *
16
+ * Optionally:
17
+ * jquery.ui.sortable.js
18
+ */
19
+
20
+ /* global jQuery:true */
21
+
22
+ /**
23
+ jQuery UI based implementation of the Plupload API - multi-runtime file uploading API.
24
+
25
+ To use the widget you must include _jQuery_ and _jQuery UI_ bundle (including `ui.core`, `ui.widget`, `ui.button`,
26
+ `ui.progressbar` and `ui.sortable`).
27
+
28
+ In general the widget is designed the way that you do not usually need to do anything to it after you instantiate it.
29
+ But! You still can intervenue, to some extent, in case you need to. Although, due to the fact that widget is based on
30
+ _jQuery UI_ widget factory, there are some specifics. See examples below for more details.
31
+
32
+ @example
33
+ <!-- Instantiating: -->
34
+ <div id="uploader">
35
+ <p>Your browser doesn't have Flash, Silverlight or HTML5 support.</p>
36
+ </div>
37
+
38
+ <script>
39
+ $('#uploader').plupload({
40
+ url : '../upload.php',
41
+ filters : [
42
+ {title : "Image files", extensions : "jpg,gif,png"}
43
+ ],
44
+ rename: true,
45
+ sortable: true,
46
+ flash_swf_url : '../../js/Moxie.swf',
47
+ silverlight_xap_url : '../../js/Moxie.xap',
48
+ });
49
+ </script>
50
+
51
+ @example
52
+ // Invoking methods:
53
+ $('#uploader').plupload(options);
54
+
55
+ // Display welcome message in the notification area
56
+ $('#uploader').plupload('notify', 'info', "This might be obvious, but you need to click 'Add Files' to add some files.");
57
+
58
+ @example
59
+ // Subscribing to the events...
60
+ // ... on initialization:
61
+ $('#uploader').plupload({
62
+ ...
63
+ viewchanged: function(event, args) {
64
+ // stuff ...
65
+ }
66
+ });
67
+ // ... or after initialization
68
+ $('#uploader').on("viewchanged", function(event, args) {
69
+ // stuff ...
70
+ });
71
+
72
+ @class UI.Plupload
73
+ @constructor
74
+ @param {Object} settings For detailed information about each option check documentation.
75
+ @param {String} settings.url URL of the server-side upload handler.
76
+ @param {Number|String} [settings.chunk_size=0] Chunk size in bytes to slice the file into. Shorcuts with b, kb, mb, gb, tb suffixes also supported. `e.g. 204800 or "204800b" or "200kb"`. By default - disabled.
77
+ @param {String} [settings.file_data_name="file"] Name for the file field in Multipart formated message.
78
+ @param {Array} [settings.filters=[]] Set of file type filters, each one defined by hash of title and extensions. `e.g. {title : "Image files", extensions : "jpg,jpeg,gif,png"}`. Dispatches `plupload.FILE_EXTENSION_ERROR`
79
+ @param {String} [settings.flash_swf_url] URL of the Flash swf.
80
+ @param {Object} [settings.headers] Custom headers to send with the upload. Hash of name/value pairs.
81
+ @param {Number|String} [settings.max_file_size] Maximum file size that the user can pick, in bytes. Optionally supports b, kb, mb, gb, tb suffixes. `e.g. "10mb" or "1gb"`. By default - not set. Dispatches `plupload.FILE_SIZE_ERROR`.
82
+ @param {Number} [settings.max_retries=0] How many times to retry the chunk or file, before triggering Error event.
83
+ @param {Boolean} [settings.multipart=true] Whether to send file and additional parameters as Multipart formated message.
84
+ @param {Object} [settings.multipart_params] Hash of key/value pairs to send with every file upload.
85
+ @param {Boolean} [settings.multi_selection=true] Enable ability to select multiple files at once in file dialog.
86
+ @param {Boolean} [settings.prevent_duplicates=false] Do not let duplicates into the queue. Dispatches `plupload.FILE_DUPLICATE_ERROR`.
87
+ @param {String|Object} [settings.required_features] Either comma-separated list or hash of required features that chosen runtime should absolutely possess.
88
+ @param {Object} [settings.resize] Enable resizng of images on client-side. Applies to `image/jpeg` and `image/png` only. `e.g. {width : 200, height : 200, quality : 90, crop: true}`
89
+ @param {Number} [settings.resize.width] If image is bigger, it will be resized.
90
+ @param {Number} [settings.resize.height] If image is bigger, it will be resized.
91
+ @param {Number} [settings.resize.quality=90] Compression quality for jpegs (1-100).
92
+ @param {Boolean} [settings.resize.crop=false] Whether to crop images to exact dimensions. By default they will be resized proportionally.
93
+ @param {String} [settings.runtimes="html5,flash,silverlight,html4"] Comma separated list of runtimes, that Plupload will try in turn, moving to the next if previous fails.
94
+ @param {String} [settings.silverlight_xap_url] URL of the Silverlight xap.
95
+ @param {Boolean} [settings.unique_names=false] If true will generate unique filenames for uploaded files.
96
+
97
+ @param {Boolean} [settings.autostart=false] Whether to auto start uploading right after file selection.
98
+ @param {Boolean} [settings.dragdrop=true] Enable ability to add file to the queue by drag'n'dropping them from the desktop.
99
+ @param {Boolean} [settings.rename=false] Enable ability to rename files in the queue.
100
+ @param {Boolean} [settings.sortable=false] Enable ability to sort files in the queue, changing their uploading priority.
101
+ @param {Object} [settings.buttons] Control the visibility of functional buttons.
102
+ @param {Boolean} [settings.buttons.browse=true] Display browse button.
103
+ @param {Boolean} [settings.buttons.start=true] Display start button.
104
+ @param {Boolean} [settings.buttons.stop=true] Display stop button.
105
+ @param {Object} [settings.views] Control various views of the file queue.
106
+ @param {Boolean} [settings.views.list=true] Enable list view.
107
+ @param {Boolean} [settings.views.thumbs=false] Enable thumbs view.
108
+ @param {String} [settings.views.default='list'] Default view.
109
+ @param {Boolean} [settings.views.remember=true] Whether to remember the current view (requires jQuery Cookie plugin).
110
+ @param {Boolean} [settings.multiple_queues=true] Re-activate the widget after each upload procedure.
111
+ @param {Number} [settings.max_file_count=0] Limit the number of files user is able to upload in one go, autosets _multiple_queues_ to _false_ (default is 0 - no limit).
112
+ */
113
+ (function(window, document, plupload, $) {
114
+
115
+ /**
116
+ Dispatched when the widget is initialized and ready.
117
+
118
+ @event ready
119
+ @param {plupload.Uploader} uploader Uploader instance sending the event.
120
+ */
121
+
122
+ /**
123
+ Dispatched when file dialog is closed.
124
+
125
+ @event selected
126
+ @param {plupload.Uploader} uploader Uploader instance sending the event.
127
+ @param {Array} files Array of selected files represented by plupload.File objects
128
+ */
129
+
130
+ /**
131
+ Dispatched when file dialog is closed.
132
+
133
+ @event removed
134
+ @param {plupload.Uploader} uploader Uploader instance sending the event.
135
+ @param {Array} files Array of removed files represented by plupload.File objects
136
+ */
137
+
138
+ /**
139
+ Dispatched when upload is started.
140
+
141
+ @event start
142
+ @param {plupload.Uploader} uploader Uploader instance sending the event.
143
+ */
144
+
145
+ /**
146
+ Dispatched when upload is stopped.
147
+
148
+ @event stop
149
+ @param {plupload.Uploader} uploader Uploader instance sending the event.
150
+ */
151
+
152
+ /**
153
+ Dispatched during the upload process.
154
+
155
+ @event progress
156
+ @param {plupload.Uploader} uploader Uploader instance sending the event.
157
+ @param {plupload.File} file File that is being uploaded (includes loaded and percent properties among others).
158
+ @param {Number} size Total file size in bytes.
159
+ @param {Number} loaded Number of bytes uploaded of the files total size.
160
+ @param {Number} percent Number of percentage uploaded of the file.
161
+ */
162
+
163
+ /**
164
+ Dispatched when file is uploaded.
165
+
166
+ @event uploaded
167
+ @param {plupload.Uploader} uploader Uploader instance sending the event.
168
+ @param {plupload.File} file File that was uploaded.
169
+ @param {Enum} status Status constant matching the plupload states QUEUED, UPLOADING, FAILED, DONE.
170
+ */
171
+
172
+ /**
173
+ Dispatched when upload of the whole queue is complete.
174
+
175
+ @event complete
176
+ @param {plupload.Uploader} uploader Uploader instance sending the event.
177
+ @param {Array} files Array of uploaded files represented by plupload.File objects
178
+ */
179
+
180
+ /**
181
+ Dispatched when the view is changed, e.g. from `list` to `thumbs` or vice versa.
182
+
183
+ @event viewchanged
184
+ @param {plupload.Uploader} uploader Uploader instance sending the event.
185
+ @param {String} type Current view type.
186
+ */
187
+
188
+ /**
189
+ Dispatched when error of some kind is detected.
190
+
191
+ @event error
192
+ @param {plupload.Uploader} uploader Uploader instance sending the event.
193
+ @param {String} error Error message.
194
+ @param {plupload.File} file File that was uploaded.
195
+ @param {Enum} status Status constant matching the plupload states QUEUED, UPLOADING, FAILED, DONE.
196
+ */
197
+
198
+ var uploaders = {};
199
+
200
+ function _(str) {
201
+ return plupload.translate(str) || str;
202
+ }
203
+
204
+ function renderUI(obj) {
205
+ obj.id = obj.attr('id');
206
+
207
+ obj.html(
208
+ '<div class="plupload_wrapper">' +
209
+ '<div class="ui-widget-content plupload_container">' +
210
+ '<div class="ui-state-default ui-widget-header plupload_header">' +
211
+ '<div class="plupload_header_content">' +
212
+ '<div class="plupload_logo"> </div>' +
213
+ '<div class="plupload_header_title">' + _('Select files') + '</div>' +
214
+ '<div class="plupload_header_text">' + _('Add files to the upload queue and click the start button.') + '</div>' +
215
+ '<div class="plupload_view_switch">' +
216
+ '<input type="radio" id="'+obj.id+'_view_list" name="view_mode_'+obj.id+'" checked="checked" /> <label class="plupload_button" for="'+obj.id+'_view_list" data-view="list">' + _('List') + '</label>' +
217
+ '<input type="radio" id="'+obj.id+'_view_thumbs" name="view_mode_'+obj.id+'" /> <label class="plupload_button" for="'+obj.id+'_view_thumbs" data-view="thumbs">' + _('Thumbnails') + '</label>' +
218
+ '</div>' +
219
+ '</div>' +
220
+ '</div>' +
221
+
222
+ '<table class="plupload_filelist plupload_filelist_header ui-widget-header">' +
223
+ '<tr>' +
224
+ '<td class="plupload_cell plupload_file_name">' + _('Filename') + '</td>' +
225
+ '<td class="plupload_cell plupload_file_status">' + _('Status') + '</td>' +
226
+ '<td class="plupload_cell plupload_file_size">' + _('Size') + '</td>' +
227
+ '<td class="plupload_cell plupload_file_action">&nbsp;</td>' +
228
+ '</tr>' +
229
+ '</table>' +
230
+
231
+ '<div class="plupload_content">' +
232
+ '<div class="plupload_droptext">' + _("Drag files here.") + '</div>' +
233
+ '<ul class="plupload_filelist_content"> </ul>' +
234
+ '<div class="plupload_clearer">&nbsp;</div>' +
235
+ '</div>' +
236
+
237
+ '<table class="plupload_filelist plupload_filelist_footer ui-widget-header">' +
238
+ '<tr>' +
239
+ '<td class="plupload_cell plupload_file_name">' +
240
+ '<div class="plupload_buttons"><!-- Visible -->' +
241
+ '<a class="plupload_button plupload_add">' + _('Add Files') + '</a>&nbsp;' +
242
+ '<a class="plupload_button plupload_start">' + _('Start Upload') + '</a>&nbsp;' +
243
+ '<a class="plupload_button plupload_stop plupload_hidden">'+_('Stop Upload') + '</a>&nbsp;' +
244
+ '</div>' +
245
+
246
+ '<div class="plupload_started plupload_hidden"><!-- Hidden -->' +
247
+ '<div class="plupload_progress plupload_right">' +
248
+ '<div class="plupload_progress_container"></div>' +
249
+ '</div>' +
250
+
251
+ '<div class="plupload_cell plupload_upload_status"></div>' +
252
+
253
+ '<div class="plupload_clearer">&nbsp;</div>' +
254
+ '</div>' +
255
+ '</td>' +
256
+ '<td class="plupload_file_status"><span class="plupload_total_status">0%</span></td>' +
257
+ '<td class="plupload_file_size"><span class="plupload_total_file_size">0 kb</span></td>' +
258
+ '<td class="plupload_file_action"></td>' +
259
+ '</tr>' +
260
+ '</table>' +
261
+
262
+ '</div>' +
263
+ '<input class="plupload_count" value="0" type="hidden">' +
264
+ '</div>'
265
+ );
266
+ }
267
+
268
+
269
+ $.widget("ui.plupload", {
270
+
271
+ widgetEventPrefix: '',
272
+
273
+ imgs: {},
274
+
275
+ contents_bak: '',
276
+
277
+ options: {
278
+ browse_button_hover: 'ui-state-hover',
279
+ browse_button_active: 'ui-state-active',
280
+
281
+ // widget specific
282
+ dragdrop : true,
283
+ multiple_queues: true, // re-use widget by default
284
+ buttons: {
285
+ browse: true,
286
+ start: true,
287
+ stop: true
288
+ },
289
+ views: {
290
+ list: true,
291
+ thumbs: false,
292
+ active: 'list',
293
+ remember: true // requires: https://github.com/carhartl/jquery-cookie, otherwise disabled even if set to true
294
+ },
295
+ autostart: false,
296
+ sortable: false,
297
+ rename: false,
298
+ max_file_count: 0 // unlimited
299
+ },
300
+
301
+ FILE_COUNT_ERROR: -9001,
302
+
303
+ _create: function() {
304
+ var id = this.element.attr('id');
305
+ if (!id) {
306
+ id = plupload.guid();
307
+ this.element.attr('id', id);
308
+ }
309
+ this.id = id;
310
+
311
+ // backup the elements initial state
312
+ this.contents_bak = this.element.html();
313
+ renderUI(this.element);
314
+
315
+ // container, just in case
316
+ this.container = $('.plupload_container', this.element).attr('id', id + '_container');
317
+
318
+ this.content = $('.plupload_content', this.element);
319
+
320
+ if ($.fn.resizable) {
321
+ this.container.resizable({
322
+ handles: 's',
323
+ minHeight: 300
324
+ });
325
+ }
326
+
327
+ // list of files, may become sortable
328
+ this.filelist = $('.plupload_filelist_content', this.container)
329
+ .attr({
330
+ id: id + '_filelist',
331
+ unselectable: 'on'
332
+ });
333
+
334
+
335
+ // buttons
336
+ this.browse_button = $('.plupload_add', this.container).attr('id', id + '_browse');
337
+ this.start_button = $('.plupload_start', this.container).attr('id', id + '_start');
338
+ this.stop_button = $('.plupload_stop', this.container).attr('id', id + '_stop');
339
+ this.thumbs_switcher = $('#' + id + '_view_thumbs');
340
+ this.list_switcher = $('#' + id + '_view_list');
341
+
342
+ if ($.ui.button) {
343
+ this.browse_button.button({
344
+ icons: { primary: 'ui-icon-circle-plus' },
345
+ disabled: true
346
+ });
347
+
348
+ this.start_button.button({
349
+ icons: { primary: 'ui-icon-circle-arrow-e' },
350
+ disabled: true
351
+ });
352
+
353
+ this.stop_button.button({
354
+ icons: { primary: 'ui-icon-circle-close' }
355
+ });
356
+
357
+ this.list_switcher.button({
358
+ text: false,
359
+ icons: { secondary: "ui-icon-grip-dotted-horizontal" }
360
+ });
361
+
362
+ this.thumbs_switcher.button({
363
+ text: false,
364
+ icons: { secondary: "ui-icon-image" }
365
+ });
366
+ }
367
+
368
+ // progressbar
369
+ this.progressbar = $('.plupload_progress_container', this.container);
370
+
371
+ if ($.ui.progressbar) {
372
+ this.progressbar.progressbar();
373
+ }
374
+
375
+ // counter
376
+ this.counter = $('.plupload_count', this.element)
377
+ .attr({
378
+ id: id + '_count',
379
+ name: id + '_count'
380
+ });
381
+
382
+ // initialize uploader instance
383
+ this._initUploader();
384
+ },
385
+
386
+ _initUploader: function() {
387
+ var self = this
388
+ , id = this.id
389
+ , uploader
390
+ , options = {
391
+ container: id + '_buttons',
392
+ browse_button: id + '_browse'
393
+ }
394
+ ;
395
+
396
+ $('.plupload_buttons', this.element).attr('id', id + '_buttons');
397
+
398
+ if (self.options.dragdrop) {
399
+ this.filelist.parent().attr('id', this.id + '_dropbox');
400
+ options.drop_element = this.id + '_dropbox';
401
+ }
402
+
403
+ if (self.options.views.thumbs) {
404
+ if (o.typeOf(self.options.required_features) === 'string') {
405
+ self.options.required_features += ",display_media";
406
+ } else {
407
+ self.options.required_features = "display_media";
408
+ }
409
+ }
410
+
411
+ uploader = this.uploader = uploaders[id] = new plupload.Uploader($.extend(this.options, options));
412
+
413
+ uploader.bind('Error', function(up, err) {
414
+ var message, details = "";
415
+
416
+ message = '<strong>' + err.message + '</strong>';
417
+
418
+ switch (err.code) {
419
+ case plupload.FILE_EXTENSION_ERROR:
420
+ details = o.sprintf(_("File: %s"), err.file.name);
421
+ break;
422
+
423
+ case plupload.FILE_SIZE_ERROR:
424
+ details = o.sprintf(_("File: %f, size: %s, max file size: %m"), err.file.name, err.file.size, plupload.parseSize(self.options.max_file_size));
425
+ break;
426
+
427
+ case plupload.FILE_DUPLICATE_ERROR:
428
+ details = o.sprintf(_("%s already present in the queue."), err.file.name);
429
+ break;
430
+
431
+ case self.FILE_COUNT_ERROR:
432
+ details = o.sprintf(_("Upload element accepts only %d file(s) at a time. Extra files were stripped."), self.options.max_file_count);
433
+ break;
434
+
435
+ case plupload.IMAGE_FORMAT_ERROR :
436
+ details = _("Image format either wrong or not supported.");
437
+ break;
438
+
439
+ case plupload.IMAGE_MEMORY_ERROR :
440
+ details = _("Runtime ran out of available memory.");
441
+ break;
442
+
443
+ /* // This needs a review
444
+ case plupload.IMAGE_DIMENSIONS_ERROR :
445
+ details = o.sprintf(_('Resoultion out of boundaries! <b>%s</b> runtime supports images only up to %wx%hpx.'), up.runtime, up.features.maxWidth, up.features.maxHeight);
446
+ break; */
447
+
448
+ case plupload.HTTP_ERROR:
449
+ details = _("Upload URL might be wrong or doesn't exist.");
450
+ break;
451
+ }
452
+
453
+ message += " <br /><i>" + details + "</i>";
454
+
455
+ self._trigger('error', null, { up: up, error: err } );
456
+
457
+ // do not show UI if no runtime can be initialized
458
+ if (err.code === plupload.INIT_ERROR) {
459
+ setTimeout(function() {
460
+ self.destroy();
461
+ }, 1);
462
+ } else {
463
+ self.notify('error', message);
464
+ }
465
+ });
466
+
467
+
468
+ uploader.bind('PostInit', function(up) {
469
+ // all buttons are optional, so they can be disabled and hidden
470
+ if (!self.options.buttons.browse) {
471
+ self.browse_button.button('disable').hide();
472
+ up.disableBrowse(true);
473
+ } else {
474
+ self.browse_button.button('enable');
475
+ }
476
+
477
+ if (!self.options.buttons.start) {
478
+ self.start_button.button('disable').hide();
479
+ }
480
+
481
+ if (!self.options.buttons.stop) {
482
+ self.stop_button.button('disable').hide();
483
+ }
484
+
485
+ if (!self.options.unique_names && self.options.rename) {
486
+ self._enableRenaming();
487
+ }
488
+
489
+ if (self.options.dragdrop && up.features.dragdrop) {
490
+ self.filelist.parent().addClass('plupload_dropbox');
491
+ }
492
+
493
+ self._enableViewSwitcher();
494
+
495
+ self.start_button.click(function(e) {
496
+ if (!$(this).button('option', 'disabled')) {
497
+ self.start();
498
+ }
499
+ e.preventDefault();
500
+ });
501
+
502
+ self.stop_button.click(function(e) {
503
+ self.stop();
504
+ e.preventDefault();
505
+ });
506
+
507
+ self._trigger('ready', null, { up: up });
508
+ });
509
+
510
+
511
+ // check if file count doesn't exceed the limit
512
+ if (self.options.max_file_count) {
513
+ self.options.multiple_queues = false; // one go only
514
+
515
+ uploader.bind('FilesAdded', function(up, selectedFiles) {
516
+ var selectedCount = selectedFiles.length
517
+ , extraCount = up.files.length + selectedCount - self.options.max_file_count
518
+ ;
519
+
520
+ if (extraCount > 0) {
521
+ selectedFiles.splice(selectedCount - extraCount, extraCount);
522
+
523
+ up.trigger('Error', {
524
+ code : self.FILE_COUNT_ERROR,
525
+ message : _('File count error.')
526
+ });
527
+ }
528
+ });
529
+ }
530
+
531
+ // uploader internal events must run first
532
+ uploader.init();
533
+
534
+ uploader.bind('FilesAdded', function(up, files) {
535
+ self._addFiles(files);
536
+ self._trigger('selected', null, { up: up, files: files } );
537
+
538
+ if (self.options.autostart) {
539
+ // set a little delay to make sure that QueueChanged triggered by the core has time to complete
540
+ setTimeout(function() {
541
+ self.start();
542
+ }, 10);
543
+ }
544
+ });
545
+
546
+ uploader.bind('FilesRemoved', function(up, files) {
547
+ self._trigger('removed', null, { up: up, files: files } );
548
+ });
549
+
550
+ uploader.bind('QueueChanged', function() {
551
+ self._handleState();
552
+ self._updateTotalProgress();
553
+ });
554
+
555
+ uploader.bind('StateChanged', function() {
556
+ self._handleState();
557
+ });
558
+
559
+ uploader.bind('UploadFile', function(up, file) {
560
+ self._handleFileStatus(file);
561
+ });
562
+
563
+ uploader.bind('FileUploaded', function(up, file) {
564
+ self._handleFileStatus(file);
565
+ self._trigger('uploaded', null, { up: up, file: file } );
566
+ });
567
+
568
+ uploader.bind('UploadProgress', function(up, file) {
569
+ self._handleFileStatus(file);
570
+ self._updateTotalProgress();
571
+ self._trigger('progress', null, { up: up, file: file } );
572
+ });
573
+
574
+ uploader.bind('UploadComplete', function(up, files) {
575
+ self._addFormFields();
576
+ self._trigger('complete', null, { up: up, files: files } );
577
+ });
578
+ },
579
+
580
+
581
+ _setOption: function(key, value) {
582
+ var self = this;
583
+
584
+ if (key == 'buttons' && typeof(value) == 'object') {
585
+ value = $.extend(self.options.buttons, value);
586
+
587
+ if (!value.browse) {
588
+ self.browse_button.button('disable').hide();
589
+ self.uploader.disableBrowse(true);
590
+ } else {
591
+ self.browse_button.button('enable').show();
592
+ self.uploader.disableBrowse(false);
593
+ }
594
+
595
+ if (!value.start) {
596
+ self.start_button.button('disable').hide();
597
+ } else {
598
+ self.start_button.button('enable').show();
599
+ }
600
+
601
+ if (!value.stop) {
602
+ self.stop_button.button('disable').hide();
603
+ } else {
604
+ self.start_button.button('enable').show();
605
+ }
606
+ }
607
+
608
+ self.uploader.settings[key] = value;
609
+ },
610
+
611
+
612
+ /**
613
+ Start upload. Triggers `start` event.
614
+
615
+ @method start
616
+ */
617
+ start: function() {
618
+ this.uploader.start();
619
+ this._trigger('start', null, { up: this.uploader });
620
+ },
621
+
622
+
623
+ /**
624
+ Stop upload. Triggers `stop` event.
625
+
626
+ @method stop
627
+ */
628
+ stop: function() {
629
+ this.uploader.stop();
630
+ this._trigger('stop', null, { up: this.uploader });
631
+ },
632
+
633
+
634
+ /**
635
+ Enable browse button.
636
+
637
+ @method enable
638
+ */
639
+ enable: function() {
640
+ this.browse_button.button('enable');
641
+ this.uploader.disableBrowse(false);
642
+ },
643
+
644
+
645
+ /**
646
+ Disable browse button.
647
+
648
+ @method disable
649
+ */
650
+ disable: function() {
651
+ this.browse_button.button('disable');
652
+ this.uploader.disableBrowse(true);
653
+ },
654
+
655
+
656
+ /**
657
+ Retrieve file by it's unique id.
658
+
659
+ @method getFile
660
+ @param {String} id Unique id of the file
661
+ @return {plupload.File}
662
+ */
663
+ getFile: function(id) {
664
+ var file;
665
+
666
+ if (typeof id === 'number') {
667
+ file = this.uploader.files[id];
668
+ } else {
669
+ file = this.uploader.getFile(id);
670
+ }
671
+ return file;
672
+ },
673
+
674
+ /**
675
+ Return array of files currently in the queue.
676
+
677
+ @method getFiles
678
+ @return {Array} Array of files in the queue represented by plupload.File objects
679
+ */
680
+ getFiles: function() {
681
+ return this.uploader.files;
682
+ },
683
+
684
+
685
+ /**
686
+ Remove the file from the queue.
687
+
688
+ @method removeFile
689
+ @param {plupload.File|String} file File to remove, might be specified directly or by it's unique id
690
+ */
691
+ removeFile: function(file) {
692
+ if (plupload.typeOf(file) === 'string') {
693
+ file = this.getFile(file);
694
+ }
695
+ this._removeFiles(file);
696
+ },
697
+
698
+
699
+ /**
700
+ Clear the file queue.
701
+
702
+ @method clearQueue
703
+ */
704
+ clearQueue: function() {
705
+ this.uploader.splice();
706
+ },
707
+
708
+
709
+ /**
710
+ Retrieve internal plupload.Uploader object (usually not required).
711
+
712
+ @method getUploader
713
+ @return {plupload.Uploader}
714
+ */
715
+ getUploader: function() {
716
+ return this.uploader;
717
+ },
718
+
719
+
720
+ /**
721
+ Trigger refresh procedure, specifically browse_button re-measure and re-position operations.
722
+ Might get handy, when UI Widget is placed within the popup, that is constantly hidden and shown
723
+ again - without calling this method after each show operation, dialog trigger might get displaced
724
+ and disfunctional.
725
+
726
+ @method refresh
727
+ */
728
+ refresh: function() {
729
+ this.uploader.refresh();
730
+ },
731
+
732
+
733
+ /**
734
+ Display a message in notification area.
735
+
736
+ @method notify
737
+ @param {Enum} type Type of the message, either `error` or `info`
738
+ @param {String} message The text message to display.
739
+ */
740
+ notify: function(type, message) {
741
+ var popup = $(
742
+ '<div class="plupload_message">' +
743
+ '<span class="plupload_message_close ui-icon ui-icon-circle-close" title="'+_('Close')+'"></span>' +
744
+ '<p><span class="ui-icon"></span>' + message + '</p>' +
745
+ '</div>'
746
+ );
747
+
748
+ popup
749
+ .addClass('ui-state-' + (type === 'error' ? 'error' : 'highlight'))
750
+ .find('p .ui-icon')
751
+ .addClass('ui-icon-' + (type === 'error' ? 'alert' : 'info'))
752
+ .end()
753
+ .find('.plupload_message_close')
754
+ .click(function() {
755
+ popup.remove();
756
+ })
757
+ .end();
758
+
759
+ $('.plupload_header', this.container).append(popup);
760
+ },
761
+
762
+
763
+ /**
764
+ Destroy the widget, the uploader, free associated resources and bring back original html.
765
+
766
+ @method destroy
767
+ */
768
+ destroy: function() {
769
+ this._removeFiles([].slice.call(this.uploader.files));
770
+
771
+ // destroy uploader instance
772
+ this.uploader.destroy();
773
+
774
+ // unbind all button events
775
+ $('.plupload_button', this.element).unbind();
776
+
777
+ // destroy buttons
778
+ if ($.ui.button) {
779
+ $('.plupload_add, .plupload_start, .plupload_stop', this.container)
780
+ .button('destroy');
781
+ }
782
+
783
+ // destroy progressbar
784
+ if ($.ui.progressbar) {
785
+ this.progressbar.progressbar('destroy');
786
+ }
787
+
788
+ // destroy sortable behavior
789
+ if ($.ui.sortable && this.options.sortable) {
790
+ $('tbody', this.filelist).sortable('destroy');
791
+ }
792
+
793
+ // restore the elements initial state
794
+ this.element
795
+ .empty()
796
+ .html(this.contents_bak);
797
+ this.contents_bak = '';
798
+
799
+ $.Widget.prototype.destroy.apply(this);
800
+ },
801
+
802
+
803
+ _handleState: function() {
804
+ var up = this.uploader;
805
+
806
+ if (up.state === plupload.STARTED) {
807
+ $(this.start_button).button('disable');
808
+
809
+ $([])
810
+ .add(this.stop_button)
811
+ .add('.plupload_started')
812
+ .removeClass('plupload_hidden');
813
+
814
+ $('.plupload_upload_status', this.element).html(o.sprintf(_('Uploaded %d/%d files'), up.total.uploaded, up.files.length));
815
+ $('.plupload_header_content', this.element).addClass('plupload_header_content_bw');
816
+ } else if (up.state === plupload.STOPPED) {
817
+ $([])
818
+ .add(this.stop_button)
819
+ .add('.plupload_started')
820
+ .addClass('plupload_hidden');
821
+
822
+ if (this.options.multiple_queues) {
823
+ $('.plupload_header_content', this.element).removeClass('plupload_header_content_bw');
824
+ } else {
825
+ $([])
826
+ .add(this.browse_button)
827
+ .add(this.start_button)
828
+ .button('disable');
829
+
830
+ up.disableBrowse();
831
+ }
832
+
833
+ if (up.files.length === (up.total.uploaded + up.total.failed)) {
834
+ this.start_button.button('disable');
835
+ } else {
836
+ this.start_button.button('enable');
837
+ }
838
+
839
+ this._updateTotalProgress();
840
+ }
841
+
842
+ if (up.total.queued === 0) {
843
+ $('.ui-button-text', this.browse_button).html(_('Add Files'));
844
+ } else {
845
+ $('.ui-button-text', this.browse_button).html(o.sprintf(_('%d files queued'), up.total.queued));
846
+ }
847
+
848
+ up.refresh();
849
+ },
850
+
851
+
852
+ _handleFileStatus: function(file) {
853
+ var self = this, actionClass, iconClass;
854
+
855
+ // since this method might be called asynchronously, file row might not yet be rendered
856
+ if (!$('#' + file.id).length) {
857
+ return;
858
+ }
859
+
860
+ switch (file.status) {
861
+ case plupload.DONE:
862
+ actionClass = 'plupload_done';
863
+ iconClass = 'ui-icon ui-icon-circle-check';
864
+ break;
865
+
866
+ case plupload.FAILED:
867
+ actionClass = 'ui-state-error plupload_failed';
868
+ iconClass = 'ui-icon ui-icon-alert';
869
+ break;
870
+
871
+ case plupload.QUEUED:
872
+ actionClass = 'plupload_delete';
873
+ iconClass = 'ui-icon ui-icon-circle-minus';
874
+ break;
875
+
876
+ case plupload.UPLOADING:
877
+ actionClass = 'ui-state-highlight plupload_uploading';
878
+ iconClass = 'ui-icon ui-icon-circle-arrow-w';
879
+
880
+ // scroll uploading file into the view if its bottom boundary is out of it
881
+ var scroller = $('.plupload_scroll', this.container)
882
+ , scrollTop = scroller.scrollTop()
883
+ , scrollerHeight = scroller.height()
884
+ , rowOffset = $('#' + file.id).position().top + $('#' + file.id).height()
885
+ ;
886
+
887
+ if (scrollerHeight < rowOffset) {
888
+ scroller.scrollTop(scrollTop + rowOffset - scrollerHeight);
889
+ }
890
+
891
+ // Set file specific progress
892
+ $('#' + file.id)
893
+ .find('.plupload_file_percent')
894
+ .html(file.percent + '%')
895
+ .end()
896
+ .find('.plupload_file_progress')
897
+ .css('width', file.percent + '%')
898
+ .end()
899
+ .find('.plupload_file_size')
900
+ .html(plupload.formatSize(file.size));
901
+ break;
902
+ }
903
+ actionClass += ' ui-state-default plupload_file';
904
+
905
+ $('#' + file.id)
906
+ .attr('class', actionClass)
907
+ .find('.ui-icon')
908
+ .attr('class', iconClass)
909
+ .end()
910
+ .filter('.plupload_delete, .plupload_done, .plupload_failed')
911
+ .find('.ui-icon')
912
+ .click(function(e) {
913
+ self._removeFiles(file);
914
+ e.preventDefault();
915
+ });
916
+ },
917
+
918
+
919
+ _updateTotalProgress: function() {
920
+ var up = this.uploader;
921
+
922
+ // Scroll to end of file list
923
+ this.filelist[0].scrollTop = this.filelist[0].scrollHeight;
924
+
925
+ this.progressbar.progressbar('value', up.total.percent);
926
+
927
+ this.element
928
+ .find('.plupload_total_status')
929
+ .html(up.total.percent + '%')
930
+ .end()
931
+ .find('.plupload_total_file_size')
932
+ .html(plupload.formatSize(up.total.size))
933
+ .end()
934
+ .find('.plupload_upload_status')
935
+ .html(o.sprintf(_('Uploaded %d/%d files'), up.total.uploaded, up.files.length));
936
+ },
937
+
938
+
939
+ _addFiles: function(files) {
940
+ var self = this, file_html, queue = [];
941
+
942
+ file_html = '<li class="plupload_file ui-state-default" id="%id%">' +
943
+ '<div class="plupload_file_thumb"> </div>' +
944
+ '<div class="plupload_file_name" title="%name%"><span class="plupload_file_namespan">%name%</span></div>' +
945
+ '<div class="plupload_file_action"><div class="ui-icon"> </div></div>' +
946
+ '<div class="plupload_file_size">%size% </div>' +
947
+ '<div class="plupload_file_fields"> </div>' +
948
+ '</li>';
949
+
950
+ if (plupload.typeOf(files) !== 'array') {
951
+ files = [files];
952
+ }
953
+
954
+ // destroy sortable if enabled
955
+ if ($.ui.sortable && this.options.sortable) {
956
+ $('tbody', self.filelist).sortable('destroy');
957
+ }
958
+
959
+ // loop over files to add
960
+ $.each(files, function(i, file) {
961
+
962
+ self.filelist.append(file_html.replace(/%(\w+)%/g, function($0, $1) {
963
+ if ('size' === $1) {
964
+ return plupload.formatSize(file.size);
965
+ } else {
966
+ return file[$1] || '';
967
+ }
968
+ }));
969
+
970
+ if (self.options.views.thumbs) {
971
+ queue.push(function(cb) {
972
+ var img = new o.Image();
973
+
974
+ img.onload = function() {
975
+ this.embed($('#' + file.id + ' .plupload_file_thumb', self.filelist)[0], {
976
+ width: 100,
977
+ height: 60,
978
+ crop: true,
979
+ swf_url: mOxie.resolveUrl(self.options.flash_swf_url),
980
+ xap_url: mOxie.resolveUrl(self.options.silverlight_xap_url)
981
+ });
982
+ };
983
+
984
+ img.onembedded = function() {
985
+ $('#' + file.id + ' .plupload_file_thumb', self.filelist).addClass('plupload_file_thumb_loaded');
986
+ this.destroy();
987
+ setTimeout(cb, 1); // detach, otherwise ui might hang (in SilverLight for example)
988
+ };
989
+
990
+ img.onerror = function() {
991
+ var ext = file.name.match(/\.([^\.]{1,7})$/);
992
+ $('#' + file.id + ' .plupload_file_thumb', self.filelist)
993
+ .html('<div class="plupload_file_dummy ui-widget-content"><span class="ui-state-disabled">' + (ext ? ext[1] : 'none') + '</span></div>');
994
+ this.destroy();
995
+ setTimeout(cb, 1);
996
+ };
997
+ img.load(file.getSource());
998
+ });
999
+ }
1000
+
1001
+ self._handleFileStatus(file);
1002
+ });
1003
+
1004
+ if (queue.length) {
1005
+ o.inSeries(queue);
1006
+ }
1007
+
1008
+ // re-enable sortable
1009
+ if (this.options.sortable && $.ui.sortable) {
1010
+ this._enableSortingList();
1011
+ }
1012
+
1013
+ this._trigger('updatelist', null, { filelist: this.filelist });
1014
+ },
1015
+
1016
+
1017
+ _removeFiles: function(files) {
1018
+ var self = this, up = this.uploader;
1019
+
1020
+ if (plupload.typeOf(files) !== 'array') {
1021
+ files = [files];
1022
+ }
1023
+
1024
+ // destroy sortable if enabled
1025
+ if ($.ui.sortable && this.options.sortable) {
1026
+ $('tbody', self.filelist).sortable('destroy');
1027
+ }
1028
+
1029
+ $.each(files, function(i, file) {
1030
+ if (file.imgs && file.imgs.length) {
1031
+ $.each(file.imgs, function(ii, img) {
1032
+ img.destroy();
1033
+ });
1034
+ file.imgs = [];
1035
+ }
1036
+ $('#' + file.id).remove();
1037
+ up.removeFile(file);
1038
+ });
1039
+
1040
+
1041
+ if (up.files.length) {
1042
+ // re-initialize sortable
1043
+ if (this.options.sortable && $.ui.sortable) {
1044
+ this._enableSortingList();
1045
+ }
1046
+ }
1047
+
1048
+ this._trigger('updatelist', null, { filelist: this.filelist });
1049
+ },
1050
+
1051
+
1052
+ _addFormFields: function() {
1053
+ var self = this;
1054
+
1055
+ // re-add from fresh
1056
+ $('.plupload_file_fields', this.filelist).html('');
1057
+
1058
+ plupload.each(this.uploader.files, function(file, count) {
1059
+ var fields = ''
1060
+ , id = self.id + '_' + count
1061
+ ;
1062
+
1063
+ if (file.target_name) {
1064
+ fields += '<input type="hidden" name="' + id + '_tmpname" value="'+plupload.xmlEncode(file.target_name)+'" />';
1065
+ }
1066
+ fields += '<input type="hidden" name="' + id + '_name" value="'+plupload.xmlEncode(file.name)+'" />';
1067
+ fields += '<input type="hidden" name="' + id + '_status" value="' + (file.status === plupload.DONE ? 'done' : 'failed') + '" />';
1068
+
1069
+ $('#' + file.id).find('.plupload_file_fields').html(fields);
1070
+ });
1071
+
1072
+ this.counter.val(this.uploader.files.length);
1073
+ },
1074
+
1075
+
1076
+ _viewChanged: function(view) {
1077
+ // update or write a new cookie
1078
+ if (this.options.views.remember && $.cookie) {
1079
+ $.cookie('plupload_ui_view', view, { expires: 7, path: '/' });
1080
+ }
1081
+
1082
+ // ugly fix for IE6 - make content area stretchable
1083
+ if (mOxie.Env.browser === 'IE' && mOxie.Env.version < 7) {
1084
+ this.content.attr('style', 'height:expression(document.getElementById("' + this.id + '_container' + '").clientHeight - ' + (view === 'list' ? 133 : 103) + ');');
1085
+ }
1086
+
1087
+ this.container.removeClass('plupload_view_list plupload_view_thumbs').addClass('plupload_view_' + view);
1088
+ this.view_mode = view;
1089
+ this._trigger('viewchanged', null, { view: view });
1090
+ },
1091
+
1092
+
1093
+ _enableViewSwitcher: function() {
1094
+ var self = this
1095
+ , view
1096
+ , switcher = $('.plupload_view_switch', this.container)
1097
+ , buttons
1098
+ , button
1099
+ ;
1100
+
1101
+ plupload.each(['list', 'thumbs'], function(view) {
1102
+ if (!self.options.views[view]) {
1103
+ switcher.find('[for="' + self.id + '_view_' + view + '"], #'+ self.id +'_view_' + view).remove();
1104
+ }
1105
+ });
1106
+
1107
+ // check if any visible left
1108
+ buttons = switcher.find('.plupload_button');
1109
+
1110
+ if (buttons.length === 1) {
1111
+ switcher.hide();
1112
+ view = buttons.eq(0).data('view');
1113
+ this._viewChanged(view);
1114
+ } else if ($.ui.button && buttons.length > 1) {
1115
+ if (this.options.views.remember && $.cookie) {
1116
+ view = $.cookie('plupload_ui_view');
1117
+ }
1118
+
1119
+ // if wierd case, bail out to default
1120
+ if (!~plupload.inArray(view, ['list', 'thumbs'])) {
1121
+ view = this.options.views.active;
1122
+ }
1123
+
1124
+ switcher
1125
+ .show()
1126
+ .buttonset()
1127
+ .find('.ui-button')
1128
+ .click(function(e) {
1129
+ view = $(this).data('view');
1130
+ self._viewChanged(view);
1131
+ e.preventDefault(); // avoid auto scrolling to widget in IE and FF (see #850)
1132
+ });
1133
+
1134
+ // if view not active - happens when switcher wasn't clicked manually
1135
+ button = switcher.find('[for="' + self.id + '_view_'+view+'"]');
1136
+ if (button.length) {
1137
+ button.trigger('click');
1138
+ }
1139
+ } else {
1140
+ switcher.show();
1141
+ this._viewChanged(this.options.views.active);
1142
+ }
1143
+ },
1144
+
1145
+
1146
+ _enableRenaming: function() {
1147
+ var self = this;
1148
+
1149
+ this.filelist.dblclick(function(e) {
1150
+ var nameSpan = $(e.target), nameInput, file, parts, name, ext = "";
1151
+
1152
+ if (!nameSpan.hasClass('plupload_file_namespan')) {
1153
+ return;
1154
+ }
1155
+
1156
+ // Get file name and split out name and extension
1157
+ file = self.uploader.getFile(nameSpan.closest('.plupload_file')[0].id);
1158
+ name = file.name;
1159
+ parts = /^(.+)(\.[^.]+)$/.exec(name);
1160
+ if (parts) {
1161
+ name = parts[1];
1162
+ ext = parts[2];
1163
+ }
1164
+
1165
+ // Display input element
1166
+ nameInput = $('<input class="plupload_file_rename" type="text" />').width(nameSpan.width()).insertAfter(nameSpan.hide());
1167
+ nameInput.val(name).blur(function() {
1168
+ nameSpan.show().parent().scrollLeft(0).end().next().remove();
1169
+ }).keydown(function(e) {
1170
+ var nameInput = $(this);
1171
+
1172
+ if ($.inArray(e.keyCode, [13, 27]) !== -1) {
1173
+ e.preventDefault();
1174
+
1175
+ // Rename file and glue extension back on
1176
+ if (e.keyCode === 13) {
1177
+ file.name = nameInput.val() + ext;
1178
+ nameSpan.html(file.name);
1179
+ }
1180
+ nameInput.blur();
1181
+ }
1182
+ })[0].focus();
1183
+ });
1184
+ },
1185
+
1186
+
1187
+ _enableSortingList: function() {
1188
+ var self = this, filelist = $('.plupload_filelist_content', this.element);
1189
+
1190
+ if ($('.plupload_file', filelist).length < 2) {
1191
+ return;
1192
+ }
1193
+
1194
+ filelist.sortable({
1195
+ items: '.plupload_delete',
1196
+
1197
+ cancel: 'object, .plupload_clearer',
1198
+
1199
+ stop: function() {
1200
+ var files = [];
1201
+
1202
+ $.each($(this).sortable('toArray'), function(i, id) {
1203
+ files[files.length] = self.uploader.getFile(id);
1204
+ });
1205
+
1206
+ files.unshift(files.length);
1207
+ files.unshift(0);
1208
+
1209
+ // re-populate files array
1210
+ Array.prototype.splice.apply(self.uploader.files, files);
1211
+ }
1212
+ });
1213
+ }
1214
+ });
1215
+
1216
+ } (window, document, plupload, jQuery));