uploader 0.2.4 → 0.2.5

Sign up to get free protection for your applications and to get access to all the features.
data/README.rdoc CHANGED
@@ -28,7 +28,7 @@ Another option is to use jRails
28
28
  http://ennerchi.com/projects/jrails
29
29
 
30
30
  === Create a model for uploads.
31
- We recommend creating a model called upload.rb. acts_as_uploader accepts all valid options for paperclip via :has_attached_file => {}
31
+ Creat an 'Upload' model in upload.rb. acts_as_uploader accepts all valid options for paperclip via :has_attached_file => {}
32
32
 
33
33
  class Upload < ActiveRecord::Base
34
34
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.4
1
+ 0.2.5
@@ -7,7 +7,8 @@ class Uploader::UploadsController < ApplicationController
7
7
 
8
8
  def create
9
9
  # Standard, one-at-a-time, upload action
10
- @upload = @parent.uploads.build(params[:upload])
10
+ @upload = Upload.new(params[:upload])
11
+ @upload.uploadable = @parent
11
12
  @upload.creator = get_creator
12
13
  @upload.save!
13
14
  message = t('uploader.successful_upload')
@@ -34,12 +35,12 @@ class Uploader::UploadsController < ApplicationController
34
35
  end
35
36
 
36
37
  def swfupload
37
- @upload = @parent.uploads.build
38
+ @upload = Upload.new
38
39
  @upload.is_public = true if params[:is_public] == true
39
40
  @upload.creator = get_creator
41
+ @upload.uploadable = @parent
40
42
  @upload.swfupload_local = params[:Filedata]
41
43
  @upload.save!
42
- @parent.uploads << @upload
43
44
  respond_to do |format|
44
45
  format.js { render :text => get_upload_text(@upload) }
45
46
  format.json { render :json => basic_uploads_json(@upload) }
@@ -74,80 +75,91 @@ class Uploader::UploadsController < ApplicationController
74
75
 
75
76
  protected
76
77
 
77
- def get_upload_text(upload)
78
- raise 'implement get_upload_text in your controller'
79
- end
78
+ def get_upload_text(upload)
79
+ raise 'implement get_upload_text in your controller'
80
+ end
80
81
 
81
- def set_upload_for_destroy
82
- @upload = Upload.find(params[:id])
83
- end
82
+ def set_upload_for_destroy
83
+ @upload = Upload.find(params[:id])
84
+ end
84
85
 
85
- def permission_denied
86
- message = t("uploader.permission_denied")
87
- respond_to do |format|
88
- format.html do
89
- flash[:notice] = message
90
- redirect_to get_redirect(:permission_denied)
86
+ def permission_denied
87
+ message = t("uploader.permission_denied")
88
+ respond_to do |format|
89
+ format.html do
90
+ flash[:notice] = message
91
+ redirect_to get_redirect(:permission_denied)
92
+ end
93
+ format.js { render :text => message }
94
+ format.json { render :json => { :success => false, :message => message } }
91
95
  end
92
- format.js { render :text => message }
93
- format.json { render :json => { :success => false, :message => message } }
94
96
  end
95
- end
96
97
 
97
- # override this method in your controller to set the redirect file upload completion
98
- # source can be :destroy_success, :create_success, :create_failure, :permission_denied
99
- def get_redirect(source)
100
- @parent
101
- end
98
+ # override this method in your controller to set the redirect file upload completion
99
+ # source can be :destroy_success, :create_success, :create_failure, :permission_denied
100
+ def get_redirect(source)
101
+ @parent
102
+ end
102
103
 
103
- # Attempts to create an @parent object using params
104
- # or the url.
105
- def setup_parent
106
- @parent = get_parent
107
- if @parent.blank?
108
- render :text => t('muck.engine.missing_parent_error')
109
- return false
104
+ # Attempts to create an @parent object using params
105
+ # or the url.
106
+ def setup_parent(*ignore)
107
+ @parent = get_parent(ignore)
108
+ @parent = get_creator if @parent.blank?
109
+ # if @parent.blank?
110
+ # render :text => t('muck.engine.missing_parent_error')
111
+ # return false
112
+ # end
110
113
  end
111
- end
112
114
 
113
- # Tries to get parent using parent_type and parent_id from the url.
114
- # If that fails and attempt is then made using find_parent
115
- def get_parent
116
- if params[:parent_type].blank? || params[:parent_id].blank?
117
- find_parent
118
- else
119
- klass = params[:parent_type].to_s.constantize
120
- klass.find(params[:parent_id])
115
+ # Tries to get parent using parent_type and parent_id from the url.
116
+ # If that fails and attempt is then made using find_parent
117
+ # parameters:
118
+ # ignore: Names to ignore. For example if the url is /foo/1/bar?thing_id=1
119
+ # you might want to ignore thing_id so pass :thing.
120
+ def get_parent(*ignore)
121
+ if params[:parent_type].blank? || params[:parent_id].blank?
122
+ find_parent(ignore)
123
+ else
124
+ klass = params[:parent_type].to_s.constantize
125
+ klass.find(params[:parent_id])
126
+ end
121
127
  end
122
- end
123
-
124
- # Searches the params to try and find an entry ending with _id
125
- # ie article_id, user_id, etc. Will return the first value found.
126
- def find_parent
127
- params.each do |name, value|
128
- if name =~ /(.+)_id$/
129
- return $1.classify.constantize.find(value)
128
+
129
+ # Searches the params to try and find an entry ending with _id
130
+ # ie article_id, user_id, etc. Will return the first value found.
131
+ # parameters:
132
+ # ignore: Names to ignore. For example if the url is /foo/1/bar?thing_id=1
133
+ # you might want to ignore thing_id so pass 'thing' to be ignored.
134
+ def find_parent(*ignore)
135
+ ignore.flatten!
136
+ params.each do |name, value|
137
+ if name =~ /(.+)_id$/
138
+ if !ignore.include?($1)
139
+ return $1.classify.constantize.find(value)
140
+ end
141
+ end
130
142
  end
143
+ nil
131
144
  end
132
- nil
133
- end
134
145
 
135
- def filter_permissions
136
- unless has_permission_to_upload(current_user, @parent)
137
- permission_denied
146
+ def filter_permissions
147
+ unless has_permission_to_upload(current_user, @parent)
148
+ permission_denied
149
+ end
138
150
  end
139
- end
140
151
 
141
- def get_creator
142
- current_user
143
- end
152
+ def get_creator
153
+ current_user
154
+ end
144
155
 
145
- def has_permission_to_upload(user, upload_parent)
146
- upload_parent.can_upload?(user)
147
- end
156
+ def has_permission_to_upload(user, upload_parent)
157
+ return true if upload_parent.blank? # upload will not be connected with a parent object only with the user
158
+ upload_parent.can_upload?(user)
159
+ end
148
160
 
149
- def basic_uploads_json(upload)
150
- upload.to_json(:only => [:id, :file_name], :methods => [:icon])
151
- end
161
+ def basic_uploads_json(upload)
162
+ upload.to_json(:only => [:id], :methods => [:icon, :thumb, :file_name])
163
+ end
152
164
 
153
165
  end
@@ -29,6 +29,7 @@ module UploaderHelper
29
29
  end
30
30
 
31
31
  def make_parent_params(parent)
32
+ return {} if parent.blank?
32
33
  { :parent_id => parent.id, :parent_type => parent.class.to_s }
33
34
  end
34
35
 
@@ -25,7 +25,7 @@
25
25
 
26
26
  var <%=container_prefix%>swfu;
27
27
 
28
- jQuery(document).ready(function() {
28
+ window.onload = function () {
29
29
  var settings = {
30
30
 
31
31
  flash_url : '/swf/swfupload.swf',
@@ -76,7 +76,7 @@
76
76
  };
77
77
 
78
78
  <%=container_prefix%>swfu = new SWFUpload(settings);
79
- });
79
+ };
80
80
 
81
81
  </script>
82
82
  <% end -%>
@@ -14,7 +14,11 @@ module ActiveRecord
14
14
  # :url => "/uploads/:class/:id/:style_:basename.:extension",
15
15
  # :path => ":rails_root/public/uploads/:class/:id/:style_:basename.:extension",
16
16
  # :styles => { :icon => "30x30!", :thumb => "100>", :small => "150>", :medium => "300>", :large => "660>"},
17
- # :default_url => "/images/profile_default.jpg" }
17
+ # :default_url => "/images/profile_default.jpg" },
18
+ # :disable_halt_nonimage_processing => false
19
+ #
20
+ # disable_halt_nonimage_processing - By default all post processing is turned off for non image files. This is useful if you want to setup styles to generate thumbnails for
21
+ # images but don't want the default Geometry processor to die on non-image files.
18
22
  def acts_as_uploader(options)
19
23
 
20
24
  #Named scopes
@@ -26,6 +30,7 @@ module ActiveRecord
26
30
  named_scope :documents, :conditions => "local_content_type IN (#{(Uploader::MimeTypeGroups::WORD_TYPES + Uploader::MimeTypeGroups::EXCEL_TYPES + Uploader::MimeTypeGroups::PDF_TYPES).collect{|type| "'#{type}'"}.join(',')})"
27
31
  named_scope :files, :conditions => "local_content_type NOT IN (#{Uploader::MimeTypeGroups::IMAGE_TYPES.collect{|type| "'#{type}'"}.join(',')})"
28
32
  named_scope :since, lambda { |*args| { :conditions => ["created_at > ?", (args.first || 7.days.ago.to_s(:db)) ]} }
33
+ named_scope :created_by, lambda { |*args| { :conditions => ["creator_id = ?", (args.first) ]} }
29
34
  named_scope :pending_s3_migration, lambda { { :conditions => ["remote_file_name IS NULL AND created_at <= ?", 20.minutes.ago.to_s(:db)], :order => 'created_at DESC' } }
30
35
 
31
36
  # Paperclip
@@ -40,6 +45,7 @@ module ActiveRecord
40
45
  class_eval <<-EOV
41
46
 
42
47
  before_post_process :transliterate_file_name
48
+ before_post_process :halt_nonimage_processing unless options[:disable_halt_nonimage_processing]
43
49
  before_create :add_width_and_height
44
50
 
45
51
  # prevents a user from submitting a crafted form that bypasses activation
@@ -144,6 +150,13 @@ module ActiveRecord
144
150
  end
145
151
  end
146
152
 
153
+ # Only works for images
154
+ def thumb
155
+ if self.is_image?
156
+ self.file.url(:thumb)
157
+ end
158
+ end
159
+
147
160
  def display_name
148
161
  CGI::escapeHTML(self.local_file_name)
149
162
  end
@@ -224,6 +237,12 @@ module ActiveRecord
224
237
  end
225
238
  end
226
239
 
240
+ def halt_nonimage_processing
241
+ if !self.is_image? && self.local.options[:styles]
242
+ return false
243
+ end
244
+ end
245
+
227
246
  end
228
247
  end
229
248
  end
Binary file
@@ -50,7 +50,7 @@ SWFUpload.prototype.initSWFUpload = function (settings) {
50
50
  /* *************** */
51
51
  SWFUpload.instances = {};
52
52
  SWFUpload.movieCount = 0;
53
- SWFUpload.version = "2.2.0 Beta 3";
53
+ SWFUpload.version = "2.2.0 2009-03-25";
54
54
  SWFUpload.QUEUE_ERROR = {
55
55
  QUEUE_LIMIT_EXCEEDED : -100,
56
56
  FILE_EXCEEDS_SIZE_LIMIT : -110,
@@ -91,6 +91,27 @@ SWFUpload.WINDOW_MODE = {
91
91
  OPAQUE : "opaque"
92
92
  };
93
93
 
94
+ // Private: takes a URL, determines if it is relative and converts to an absolute URL
95
+ // using the current site. Only processes the URL if it can, otherwise returns the URL untouched
96
+ SWFUpload.completeURL = function(url) {
97
+ if (typeof(url) !== "string" || url.match(/^https?:\/\//i) || url.match(/^\//)) {
98
+ return url;
99
+ }
100
+
101
+ var currentURL = window.location.protocol + "//" + window.location.hostname + (window.location.port ? ":" + window.location.port : "");
102
+
103
+ var indexSlash = window.location.pathname.lastIndexOf("/");
104
+ if (indexSlash <= 0) {
105
+ path = "/";
106
+ } else {
107
+ path = window.location.pathname.substr(0, indexSlash) + "/";
108
+ }
109
+
110
+ return /*currentURL +*/ path + url;
111
+
112
+ };
113
+
114
+
94
115
  /* ******************** */
95
116
  /* Instance Members */
96
117
  /* ******************** */
@@ -104,11 +125,13 @@ SWFUpload.prototype.initSettings = function () {
104
125
 
105
126
  // Upload backend settings
106
127
  this.ensureDefault("upload_url", "");
128
+ this.ensureDefault("preserve_relative_urls", false);
107
129
  this.ensureDefault("file_post_name", "Filedata");
108
130
  this.ensureDefault("post_params", {});
109
131
  this.ensureDefault("use_query_string", false);
110
132
  this.ensureDefault("requeue_on_error", false);
111
133
  this.ensureDefault("http_success", []);
134
+ this.ensureDefault("assume_success_timeout", 0);
112
135
 
113
136
  // File Settings
114
137
  this.ensureDefault("file_types", "*.*");
@@ -131,7 +154,8 @@ SWFUpload.prototype.initSettings = function () {
131
154
  this.ensureDefault("button_text_left_padding", 0);
132
155
  this.ensureDefault("button_action", SWFUpload.BUTTON_ACTION.SELECT_FILES);
133
156
  this.ensureDefault("button_disabled", false);
134
- this.ensureDefault("button_placeholder_id", null);
157
+ this.ensureDefault("button_placeholder_id", "");
158
+ this.ensureDefault("button_placeholder", null);
135
159
  this.ensureDefault("button_cursor", SWFUpload.CURSOR.ARROW);
136
160
  this.ensureDefault("button_window_mode", SWFUpload.WINDOW_MODE.WINDOW);
137
161
 
@@ -161,57 +185,21 @@ SWFUpload.prototype.initSettings = function () {
161
185
  this.customSettings = this.settings.custom_settings;
162
186
 
163
187
  // Update the flash url if needed
164
- if (this.settings.prevent_swf_caching) {
165
- this.settings.flash_url = this.settings.flash_url + "?swfuploadrnd=" + Math.floor(Math.random() * 999999999);
188
+ if (!!this.settings.prevent_swf_caching) {
189
+ this.settings.flash_url = this.settings.flash_url + (this.settings.flash_url.indexOf("?") < 0 ? "?" : "&") + "preventswfcaching=" + new Date().getTime();
166
190
  }
167
191
 
168
- delete this.ensureDefault;
169
- };
170
-
171
- SWFUpload.prototype.loadFlash = function () {
172
- if (this.settings.button_placeholder_id !== "") {
173
- this.replaceWithFlash();
174
- } else {
175
- this.appendFlash();
192
+ if (!this.settings.preserve_relative_urls) {
193
+ //this.settings.flash_url = SWFUpload.completeURL(this.settings.flash_url); // Don't need to do this one since flash doesn't look at it
194
+ this.settings.upload_url = SWFUpload.completeURL(this.settings.upload_url);
195
+ this.settings.button_image_url = SWFUpload.completeURL(this.settings.button_image_url);
176
196
  }
177
- };
178
-
179
- // Private: appendFlash gets the HTML tag for the Flash
180
- // It then appends the flash to the body
181
- SWFUpload.prototype.appendFlash = function () {
182
- var targetElement, container;
183
-
184
- // Make sure an element with the ID we are going to use doesn't already exist
185
- if (document.getElementById(this.movieName) !== null) {
186
- throw "ID " + this.movieName + " is already in use. The Flash Object could not be added";
187
- }
188
-
189
- // Get the body tag where we will be adding the flash movie
190
- targetElement = document.getElementsByTagName("body")[0];
191
-
192
- if (targetElement == undefined) {
193
- throw "Could not find the 'body' element.";
194
- }
195
-
196
- // Append the container and load the flash
197
- container = document.createElement("div");
198
- container.style.width = "1px";
199
- container.style.height = "1px";
200
- container.style.overflow = "hidden";
201
-
202
- targetElement.appendChild(container);
203
- container.innerHTML = this.getFlashHTML(); // Using innerHTML is non-standard but the only sensible way to dynamically add Flash in IE (and maybe other browsers)
204
-
205
- // Fix IE Flash/Form bug
206
- if (window[this.movieName] == undefined) {
207
- window[this.movieName] = this.getMovieElement();
208
- }
209
-
210
197
 
198
+ delete this.ensureDefault;
211
199
  };
212
200
 
213
- // Private: replaceWithFlash replaces the button_placeholder element with the flash movie.
214
- SWFUpload.prototype.replaceWithFlash = function () {
201
+ // Private: loadFlash replaces the button_placeholder element with the flash movie.
202
+ SWFUpload.prototype.loadFlash = function () {
215
203
  var targetElement, tempParent;
216
204
 
217
205
  // Make sure an element with the ID we are going to use doesn't already exist
@@ -220,10 +208,10 @@ SWFUpload.prototype.replaceWithFlash = function () {
220
208
  }
221
209
 
222
210
  // Get the element where we will be placing the flash movie
223
- targetElement = document.getElementById(this.settings.button_placeholder_id);
211
+ targetElement = document.getElementById(this.settings.button_placeholder_id) || this.settings.button_placeholder;
224
212
 
225
213
  if (targetElement == undefined) {
226
- throw "Could not find the placeholder element.";
214
+ throw "Could not find the placeholder element: " + this.settings.button_placeholder_id;
227
215
  }
228
216
 
229
217
  // Append the container and load the flash
@@ -242,7 +230,7 @@ SWFUpload.prototype.replaceWithFlash = function () {
242
230
  SWFUpload.prototype.getFlashHTML = function () {
243
231
  // Flash Satay object syntax: http://www.alistapart.com/articles/flashsatay
244
232
  return ['<object id="', this.movieName, '" type="application/x-shockwave-flash" data="', this.settings.flash_url, '" width="', this.settings.button_width, '" height="', this.settings.button_height, '" class="swfupload">',
245
- '<param name="wmode" value="', this.settings.button_window_mode , '" />',
233
+ '<param name="wmode" value="', this.settings.button_window_mode, '" />',
246
234
  '<param name="movie" value="', this.settings.flash_url, '" />',
247
235
  '<param name="quality" value="high" />',
248
236
  '<param name="menu" value="false" />',
@@ -264,6 +252,7 @@ SWFUpload.prototype.getFlashVars = function () {
264
252
  "&amp;useQueryString=", encodeURIComponent(this.settings.use_query_string),
265
253
  "&amp;requeueOnError=", encodeURIComponent(this.settings.requeue_on_error),
266
254
  "&amp;httpSuccess=", encodeURIComponent(httpSuccessString),
255
+ "&amp;assumeSuccessTimeout=", encodeURIComponent(this.settings.assume_success_timeout),
267
256
  "&amp;params=", encodeURIComponent(paramString),
268
257
  "&amp;filePostName=", encodeURIComponent(this.settings.file_post_name),
269
258
  "&amp;fileTypes=", encodeURIComponent(this.settings.file_types),
@@ -325,11 +314,12 @@ SWFUpload.prototype.destroy = function () {
325
314
  // Make sure Flash is done before we try to remove it
326
315
  this.cancelUpload(null, false);
327
316
 
317
+
328
318
  // Remove the SWFUpload DOM nodes
329
319
  var movieElement = null;
330
320
  movieElement = this.getMovieElement();
331
321
 
332
- if (movieElement) {
322
+ if (movieElement && typeof(movieElement.CallFunction) === "unknown") { // We only want to do this in IE
333
323
  // Loop through all the movie's properties and remove all function references (DOM/JS IE 6/7 memory leak workaround)
334
324
  for (var i in movieElement) {
335
325
  try {
@@ -345,7 +335,6 @@ SWFUpload.prototype.destroy = function () {
345
335
  } catch (ex) {}
346
336
  }
347
337
 
348
-
349
338
  // Remove IE form fix reference
350
339
  window[this.movieName] = null;
351
340
 
@@ -361,11 +350,12 @@ SWFUpload.prototype.destroy = function () {
361
350
 
362
351
 
363
352
  return true;
364
- } catch (ex1) {
353
+ } catch (ex2) {
365
354
  return false;
366
355
  }
367
356
  };
368
357
 
358
+
369
359
  // Public: displayDebugInfo prints out settings and configuration
370
360
  // information about this SWFUpload instance.
371
361
  // This function (and any references to it) can be deleted when placing
@@ -382,6 +372,7 @@ SWFUpload.prototype.displayDebugInfo = function () {
382
372
  "\t", "use_query_string: ", this.settings.use_query_string.toString(), "\n",
383
373
  "\t", "requeue_on_error: ", this.settings.requeue_on_error.toString(), "\n",
384
374
  "\t", "http_success: ", this.settings.http_success.join(", "), "\n",
375
+ "\t", "assume_success_timeout: ", this.settings.assume_success_timeout, "\n",
385
376
  "\t", "file_post_name: ", this.settings.file_post_name, "\n",
386
377
  "\t", "post_params: ", this.settings.post_params.toString(), "\n",
387
378
  "\t", "file_types: ", this.settings.file_types, "\n",
@@ -394,6 +385,7 @@ SWFUpload.prototype.displayDebugInfo = function () {
394
385
  "\t", "prevent_swf_caching: ", this.settings.prevent_swf_caching.toString(), "\n",
395
386
 
396
387
  "\t", "button_placeholder_id: ", this.settings.button_placeholder_id.toString(), "\n",
388
+ "\t", "button_placeholder: ", (this.settings.button_placeholder ? "Set" : "Not Set"), "\n",
397
389
  "\t", "button_image_url: ", this.settings.button_image_url.toString(), "\n",
398
390
  "\t", "button_width: ", this.settings.button_width.toString(), "\n",
399
391
  "\t", "button_height: ", this.settings.button_height.toString(), "\n",
@@ -468,7 +460,6 @@ SWFUpload.prototype.callFlash = function (functionName, argumentArray) {
468
460
  return returnValue;
469
461
  };
470
462
 
471
-
472
463
  /* *****************************
473
464
  -- Flash control methods --
474
465
  Your UI should use these
@@ -636,6 +627,11 @@ SWFUpload.prototype.setHTTPSuccess = function (http_status_codes) {
636
627
  this.callFlash("SetHTTPSuccess", [http_status_codes]);
637
628
  };
638
629
 
630
+ // Public: setHTTPSuccess changes the http_success setting
631
+ SWFUpload.prototype.setAssumeSuccessTimeout = function (timeout_seconds) {
632
+ this.settings.assume_success_timeout = timeout_seconds;
633
+ this.callFlash("SetAssumeSuccessTimeout", [timeout_seconds]);
634
+ };
639
635
 
640
636
  // Public: setDebugEnabled changes the debug_enabled setting
641
637
  SWFUpload.prototype.setDebugEnabled = function (debugEnabled) {
@@ -776,24 +772,63 @@ SWFUpload.prototype.unescapeFilePostParams = function (file) {
776
772
  return file;
777
773
  };
778
774
 
775
+ // Private: Called by Flash to see if JS can call in to Flash (test if External Interface is working)
776
+ SWFUpload.prototype.testExternalInterface = function () {
777
+ try {
778
+ return this.callFlash("TestExternalInterface");
779
+ } catch (ex) {
780
+ return false;
781
+ }
782
+ };
783
+
784
+ // Private: This event is called by Flash when it has finished loading. Don't modify this.
785
+ // Use the swfupload_loaded_handler event setting to execute custom code when SWFUpload has loaded.
779
786
  SWFUpload.prototype.flashReady = function () {
780
787
  // Check that the movie element is loaded correctly with its ExternalInterface methods defined
781
788
  var movieElement = this.getMovieElement();
782
789
 
790
+ if (!movieElement) {
791
+ this.debug("Flash called back ready but the flash movie can't be found.");
792
+ return;
793
+ }
794
+
795
+ this.cleanUp(movieElement);
796
+
797
+ this.queueEvent("swfupload_loaded_handler");
798
+ };
799
+
800
+ // Private: removes Flash added fuctions to the DOM node to prevent memory leaks in IE.
801
+ // This function is called by Flash each time the ExternalInterface functions are created.
802
+ SWFUpload.prototype.cleanUp = function (movieElement) {
783
803
  // Pro-actively unhook all the Flash functions
784
- if (typeof(movieElement.CallFunction) === "unknown") { // We only want to do this in IE
785
- this.debug("Removing Flash functions hooks (this should only run in IE and should prevent memory leaks)");
786
- for (var key in movieElement) {
787
- try {
788
- if (typeof(movieElement[key]) === "function") {
789
- movieElement[key] = null;
804
+ try {
805
+ if (this.movieElement && typeof(movieElement.CallFunction) === "unknown") { // We only want to do this in IE
806
+ this.debug("Removing Flash functions hooks (this should only run in IE and should prevent memory leaks)");
807
+ for (var key in movieElement) {
808
+ try {
809
+ if (typeof(movieElement[key]) === "function") {
810
+ movieElement[key] = null;
811
+ }
812
+ } catch (ex) {
790
813
  }
791
- } catch (ex) {
792
814
  }
793
815
  }
794
- }
816
+ } catch (ex1) {
795
817
 
796
- this.queueEvent("swfupload_loaded_handler");
818
+ }
819
+
820
+ // Fix Flashes own cleanup code so if the SWFMovie was removed from the page
821
+ // it doesn't display errors.
822
+ window["__flash__removeCallback"] = function (instance, name) {
823
+ try {
824
+ if (instance) {
825
+ instance[name] = null;
826
+ }
827
+ } catch (flashEx) {
828
+
829
+ }
830
+ };
831
+
797
832
  };
798
833
 
799
834
 
@@ -818,8 +853,8 @@ SWFUpload.prototype.fileQueueError = function (file, errorCode, message) {
818
853
 
819
854
  /* Called after the file dialog has closed and the selected files have been queued.
820
855
  You could call startUpload here if you want the queued files to begin uploading immediately. */
821
- SWFUpload.prototype.fileDialogComplete = function (numFilesSelected, numFilesQueued) {
822
- this.queueEvent("file_dialog_complete_handler", [numFilesSelected, numFilesQueued]);
856
+ SWFUpload.prototype.fileDialogComplete = function (numFilesSelected, numFilesQueued, numFilesInQueue) {
857
+ this.queueEvent("file_dialog_complete_handler", [numFilesSelected, numFilesQueued, numFilesInQueue]);
823
858
  };
824
859
 
825
860
  SWFUpload.prototype.uploadStart = function (file) {
@@ -859,9 +894,9 @@ SWFUpload.prototype.uploadError = function (file, errorCode, message) {
859
894
  this.queueEvent("upload_error_handler", [file, errorCode, message]);
860
895
  };
861
896
 
862
- SWFUpload.prototype.uploadSuccess = function (file, serverData) {
897
+ SWFUpload.prototype.uploadSuccess = function (file, serverData, responseReceived) {
863
898
  file = this.unescapeFilePostParams(file);
864
- this.queueEvent("upload_success_handler", [file, serverData]);
899
+ this.queueEvent("upload_success_handler", [file, serverData, responseReceived]);
865
900
  };
866
901
 
867
902
  SWFUpload.prototype.uploadComplete = function (file) {