remotipart 0.4.2 → 1.0

Sign up to get free protection for your applications and to get access to all the features.
data/History.rdoc CHANGED
@@ -1,6 +1,13 @@
1
1
  = History
2
2
 
3
- === 0.4.2 / 2011-26-08
3
+ === 1.0 / 2011-08-26
4
+
5
+ * New Features
6
+ * New dependency on simpler jquery.iframe-transport.js (no more form.js)
7
+ * New Rack middleware, making `remotipart_response` block obsolete in js.erb responses
8
+ * Better support for all requested ajax data-types
9
+
10
+ === 0.4.2 / 2011-08-26
4
11
 
5
12
  * Minor Enhancements
6
13
  * Updated to jquery.form.js v2.84
data/README.rdoc CHANGED
@@ -1,9 +1,10 @@
1
1
  = Remotipart
2
2
 
3
- Remotipart is a Ruby on Rails gem enabling remote multipart forms (AJAX style file uploads) with jQuery.
4
- This gem augments the native Rails jQuery remote form function enabling asynchronous file uploads with little to no modification to your application.
3
+ Remotipart is a Ruby on Rails gem enabling AJAX file uploads with jQuery in Rails 3.0 and Rails 3.1 remote forms.
4
+ This gem augments the native Rails jQuery remote form functionality enabling asynchronous file uploads with little to no modification to your application.
5
5
 
6
- {View Homepage and Demos}[http://www.alfajango.com/blog/remotipart-rails-gem/]
6
+ * {Homepage and Demos}[http://www.alfajango.com/blog/remotipart-rails-gem/]
7
+ * {How AJAX File Uploads Work}[http://www.alfajango.com/blog/ajax-file-uploads-with-the-iframe-method/]
7
8
 
8
9
  == Dependencies
9
10
 
@@ -12,24 +13,33 @@ This gem augments the native Rails jQuery remote form function enabling asynchro
12
13
 
13
14
  == Installation
14
15
 
15
- <b>If you're using an old version of the jquery-rails gem,
16
- make sure you have a supported jquery-ujs (rails.js or jquery_ujs.js) version from VERSION_COMPATIBILITY.</b>
16
+ <b>Your app should be using jquery-rails gem v1.0.12 or above.</b>
17
+
18
+ If you're using an old version of the jquery-rails gem,
19
+ make sure you have a supported jquery-ujs (rails.js or jquery_ujs.js) version from {VERSION_COMPATIBILITY}[https://github.com/JangoSteve/remotipart/blob/master/VERSION_COMPATIBILITY.rdoc].
17
20
 
18
21
  [1.]
19
22
  Install the Remotipart gem
20
23
 
21
- * Add this line to your GEMFILE (add the correct version from previous section if needed)
24
+ * Add this line to your GEMFILE (use the appropriate version from the compatibilty chart if needed)
22
25
 
23
- gem 'remotipart', '~> 0.4'
26
+ gem 'remotipart', '~> 1.0'
24
27
 
25
28
  * And run
26
29
 
27
30
  bundle install
28
31
 
32
+ === Rails 3.1
33
+
34
+ [2.]
35
+ The necessary js files will automatically be added to the asset pipeline, so add the following to app/assets/javascripts/application.js (right after <tt>//= require jquery_ujs</tt>):
36
+
37
+ //= require jquery.remotipart
38
+
29
39
  === Rails 3.0
30
40
 
31
41
  [2.]
32
- Run the Remotipart install generator to add jquery.form.js and jquery.remotipart.js to public/javascripts/
42
+ Run the Remotipart install generator to add jquery.iframe-transport.js and jquery.remotipart.js to public/javascripts/
33
43
 
34
44
  rails g remotipart:install
35
45
 
@@ -38,28 +48,12 @@ make sure you have a supported jquery-ujs (rails.js or jquery_ujs.js) version fr
38
48
 
39
49
  <%= javascript_include_tag :defaults %>
40
50
 
41
- === Rails 3.1
42
-
43
- [2.]
44
- The necessary js files will automatically be added to the asset pipeline, so add the following to app/assets/javascripts/application.js (right after <tt>//= require jquery_ujs</tt>):
45
-
46
- //= require jquery.form
47
- //= require jquery.remotipart
48
-
49
51
  == Usage
50
52
 
51
53
  * For multipart / forms with file inputs, set your form_for to remote as you would for a normal ajax form:
52
54
  :remote => true
53
55
  * When Javascript is enabled in the user's browser, the form, including the file, will be submitted asynchronously to your controller with:
54
56
  :format == 'js'
55
- * In the JS response template for your controller action, wrap all of your response code in one remotipart_response block:
56
- <%= remotipart_response do %> All Javascript response code goes here <% end %>
57
- * The options available to the text_area_tag[http://api.rubyonrails.org/classes/ActionView/Helpers/FormTagHelper.html#method-i-text_area_tag] can be passed to remotipart_response for further control over the response. For instance:
58
- <%= remotipart_response({:escape => false}) do %> All Javascript response code goes here <% end %>
59
- * Anything inside the +remotipart_response+ block will be rendered normally, unless the request actually did come from a remotipart-submitted form. So <tt>js.erb</tt> responses can be shared between remotipart and non-remotipart forms.
60
- <%= remotipart_response do %>
61
- // do stuff here
62
- <% end %>
63
57
  * If you need to determine if a particular request was made via a remotipart-enabled form...
64
58
  * from your Rails controller or view:
65
59
 
@@ -93,14 +87,12 @@ sample_controller.rb
93
87
  end
94
88
 
95
89
  create.js.erb
96
- <%= remotipart_response do %>
97
- // Display a Javascript alert
98
- alert('success!');
99
- <% if remotipart_submitted? %>
100
- alert('submitted via remotipart')
101
- <% else %>
102
- alert('submitted via native jquery-ujs')
103
- <% end %>
90
+ // Display a Javascript alert
91
+ alert('success!');
92
+ <% if remotipart_submitted? %>
93
+ alert('submitted via remotipart')
94
+ <% else %>
95
+ alert('submitted via native jquery-ujs')
104
96
  <% end %>
105
97
 
106
98
  == Note on Patches/Pull Requests
@@ -115,6 +107,36 @@ create.js.erb
115
107
  (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
116
108
  * Send me a pull request. Bonus points for topic branches.
117
109
 
110
+ == Tests
111
+
112
+ Because of the nature of AJAX file uploads and certain browser restrictions, we could not simply create unit tests (using qunit or jasmine)
113
+ to test the file upload functionality of remotipart (since the browsers running those test suites won't allow us to set the target of a file
114
+ upload input using javascript). So, instead we created a demo Rails app using remotipart with all remotipart functionality tested using RSpec and Capybara.
115
+
116
+ * {Demo Rails App with Tests}[https://github.com/JangoSteve/Rails-jQuery-Demo/tree/remotipart]
117
+ * {Tests}[https://github.com/JangoSteve/Rails-jQuery-Demo/blob/remotipart/spec/integration/comments_spec.rb]
118
+
119
+ To run tests:
120
+
121
+ Clone the remotipart branch of the demo app
122
+ git clone -b remotipart git://github.com/JangoSteve/Rails-jQuery-Demo.git
123
+
124
+ Install the dependencies
125
+ bundle install
126
+
127
+ Run the tests
128
+ bundle exec rspec spec/
129
+
130
+ If you need to test your own changes to remotipart, just update the Gemfile with your own fork/branch of remotipart:
131
+
132
+ gem 'remotipart', :git => 'git://github.com/MY_FORK/remotipart.git', :branch => 'MY_BRANCH'
133
+
134
+ == Special Thanks
135
+
136
+ Thank you to Greg Leppert for writing the original version of this gem and providing inspiration for the gem in its current incarnation.
137
+
138
+ Thank you to {Adam Kerr}[https://github.com/ajrkerr] for helping move over to the simpler jQuery 1.6-compatible iframe-transport.js and for helping write the rack middleware, making remotipart even easier to use in Rails.
139
+
118
140
  == Copyright
119
141
 
120
- Copyright (c) 2011 Greg Leppert, Steve Schwartz. See LICENSE for details.
142
+ Copyright (c) 2011 {Steve Schwartz}[https://github.com/JangoSteve], {Greg Leppert}[https://github.com/leppert]. See LICENSE for details.
@@ -4,12 +4,12 @@ module Remotipart
4
4
  module Generators
5
5
  class InstallGenerator < ::Rails::Generators::Base
6
6
 
7
- desc "This generator installs Form.js #{Remotipart::Rails::FORMJS_VERSION} and Remotipart #{Remotipart::Rails::VERSION}"
7
+ desc "This generator installs IframeTransport.js #{Remotipart::Rails::IFRAMETRANSPORT_VERSION} and Remotipart #{Remotipart::Rails::VERSION}"
8
8
  source_root File.expand_path('../../../../../vendor/assets/javascripts', __FILE__)
9
9
 
10
- def install_formjs
11
- say_status "copying", "Form.js #{Remotipart::Rails::FORMJS_VERSION}", :green
12
- copy_file "jquery.form.js", "public/javascripts/jquery.form.js"
10
+ def install_iframe_transport
11
+ say_status "copying", "IframeTransport.js #{Remotipart::Rails::IFRAMETRANSPORT_VERSION}", :green
12
+ copy_file "jquery.iframe-transport.js", "public/javascripts/jquery.iframe-transport.js"
13
13
  end
14
14
 
15
15
  def install_remotipart
@@ -0,0 +1,33 @@
1
+ module Remotipart
2
+
3
+ # A middleware to look for our form parameters and
4
+ # encourage Rails to respond with the requested format
5
+ class Middleware
6
+ def initialize app
7
+ @app = app
8
+ end
9
+
10
+ def call env
11
+ # For some reason, in Rails 3.0, `env['rack.request.form_hash']`
12
+ # isn't populated unless we manually initialize a new Rack::Request
13
+ # and call the `POST` method on it
14
+ if ::Rails.version < "3.1"
15
+ Rack::Request.new(env).POST
16
+ end
17
+ params = env['rack.request.form_hash']
18
+
19
+ # This was using an iframe transport, and is therefore an XHR
20
+ # This is required if we're going to override the http_accept
21
+ if params and params['X-Requested-With'] == 'IFrame'
22
+ env['HTTP_X_REQUESTED_WITH'] = 'xmlhttprequest'
23
+ end
24
+
25
+ # Override the accepted format, because it isn't what we really want
26
+ if params and params['X-Http-Accept']
27
+ env['HTTP_ACCEPT'] = params['X-Http-Accept']
28
+ end
29
+
30
+ @app.call(env)
31
+ end
32
+ end
33
+ end
@@ -10,6 +10,11 @@ module Remotipart
10
10
 
11
11
  initializer "remotipart.controller_helper" do
12
12
  ActionController::Base.send :include, RequestHelper
13
+ ActionController::Base.send :include, RenderOverrides
14
+ end
15
+
16
+ initializer "remotipart.include_middelware" do
17
+ config.app_middleware.insert_after ActionDispatch::ParamsParser, Middleware
13
18
  end
14
19
  end
15
20
 
@@ -5,7 +5,7 @@ module Remotipart
5
5
  class Railtie < ::Rails::Railtie
6
6
  config.before_configuration do
7
7
  # Files to be added to :defaults
8
- FILES = ['jquery.form', 'jquery.remotipart']
8
+ FILES = ['jquery.iframe-transport', 'jquery.remotipart']
9
9
 
10
10
  # Figure out where rails.js (aka jquery_ujs.js if install by jquery-rails gem) is
11
11
  # in the :defaults array
@@ -29,6 +29,11 @@ module Remotipart
29
29
 
30
30
  initializer "remotipart.controller_helper" do
31
31
  ActionController::Base.send :include, RequestHelper
32
+ ActionController::Base.send :include, RenderOverrides
33
+ end
34
+
35
+ initializer "remotipart.include_middelware" do
36
+ config.app_middleware.insert_after ActionDispatch::ParamsParser, Middleware
32
37
  end
33
38
  end
34
39
 
@@ -1,6 +1,6 @@
1
1
  module Remotipart
2
2
  module Rails
3
- VERSION = "0.4.2"
4
- FORMJS_VERSION = "2.84"
3
+ VERSION = "1.0"
4
+ IFRAMETRANSPORT_VERSION = "07.05.2011"
5
5
  end
6
6
  end
@@ -0,0 +1,15 @@
1
+ module Remotipart
2
+
3
+ #Responder used to automagically wrap any non-xml replies in a text-area
4
+ # as expected by iframe-transport
5
+ module RenderOverrides
6
+ def render *args
7
+ super
8
+ if remotipart_submitted?
9
+ response.body = %{<textarea data-type=\"#{content_type}\">#{response.body}</textarea>}
10
+ response.content_type = Mime::HTML
11
+ end
12
+ response_body
13
+ end
14
+ end
15
+ end
@@ -3,6 +3,7 @@ module Remotipart
3
3
  def remotipart_submitted?
4
4
  params[:remotipart_submitted] ? true : false
5
5
  end
6
+
6
7
  alias :remotipart_requested? :remotipart_submitted?
7
8
  end
8
9
  end
@@ -1,13 +1,9 @@
1
1
  module Remotipart
2
2
  module ViewHelper
3
+ #No longer used
4
+ #Retrained to prevent issues while updating
3
5
  def remotipart_response(options = {}, &block)
4
- content = with_output_buffer(&block)
5
- if remotipart_submitted?
6
- response.content_type = Mime::HTML
7
- text_area_tag('remotipart_response', String.new(content), options)
8
- else
9
- content
10
- end
6
+ with_output_buffer(&block)
11
7
  end
12
8
  end
13
9
  end
data/lib/remotipart.rb CHANGED
@@ -1,3 +1,5 @@
1
1
  require 'remotipart/view_helper'
2
2
  require 'remotipart/request_helper'
3
+ require 'remotipart/render_overrides'
4
+ require 'remotipart/middleware'
3
5
  require 'remotipart/rails' if defined?(Rails)
data/remotipart.gemspec CHANGED
@@ -5,7 +5,7 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{remotipart}
8
- s.version = "0.4.2"
8
+ s.version = "1.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Greg Leppert", "Steve Schwartz"]
@@ -28,16 +28,18 @@ Gem::Specification.new do |s|
28
28
  "VERSION_COMPATIBILITY.rdoc",
29
29
  "lib/generators/remotipart/install/install_generator.rb",
30
30
  "lib/remotipart.rb",
31
+ "lib/remotipart/middleware.rb",
31
32
  "lib/remotipart/rails.rb",
32
33
  "lib/remotipart/rails/engine.rb",
33
34
  "lib/remotipart/rails/railtie.rb",
34
35
  "lib/remotipart/rails/version.rb",
36
+ "lib/remotipart/render_overrides.rb",
35
37
  "lib/remotipart/request_helper.rb",
36
38
  "lib/remotipart/view_helper.rb",
37
39
  "remotipart.gemspec",
38
40
  "test/helper.rb",
39
41
  "test/test_remotipart.rb",
40
- "vendor/assets/javascripts/jquery.form.js",
42
+ "vendor/assets/javascripts/jquery.iframe-transport.js",
41
43
  "vendor/assets/javascripts/jquery.remotipart.js"
42
44
  ]
43
45
  s.homepage = %q{http://www.alfajango.com/blog/remotipart-rails-gem/}
@@ -0,0 +1,233 @@
1
+ // This [jQuery](http://jquery.com/) plugin implements an `<iframe>`
2
+ // [transport](http://api.jquery.com/extending-ajax/#Transports) so that
3
+ // `$.ajax()` calls support the uploading of files using standard HTML file
4
+ // input fields. This is done by switching the exchange from `XMLHttpRequest` to
5
+ // a hidden `iframe` element containing a form that is submitted.
6
+
7
+ // The [source for the plugin](http://github.com/cmlenz/jquery-iframe-transport)
8
+ // is available on [Github](http://github.com/) and dual licensed under the MIT
9
+ // or GPL Version 2 licenses.
10
+
11
+ // ## Usage
12
+
13
+ // To use this plugin, you simply add a `iframe` option with the value `true`
14
+ // to the Ajax settings an `$.ajax()` call, and specify the file fields to
15
+ // include in the submssion using the `files` option, which can be a selector,
16
+ // jQuery object, or a list of DOM elements containing one or more
17
+ // `<input type="file">` elements:
18
+
19
+ // $("#myform").submit(function() {
20
+ // $.ajax(this.action, {
21
+ // files: $(":file", this),
22
+ // iframe: true
23
+ // }).complete(function(data) {
24
+ // console.log(data);
25
+ // });
26
+ // });
27
+
28
+ // The plugin will construct a hidden `<iframe>` element containing a copy of
29
+ // the form the file field belongs to, will disable any form fields not
30
+ // explicitly included, submit that form, and process the response.
31
+
32
+ // If you want to include other form fields in the form submission, include them
33
+ // in the `data` option, and set the `processData` option to `false`:
34
+
35
+ // $("#myform").submit(function() {
36
+ // $.ajax(this.action, {
37
+ // data: $(":text", this).serializeArray(),
38
+ // files: $(":file", this),
39
+ // iframe: true,
40
+ // processData: false
41
+ // }).complete(function(data) {
42
+ // console.log(data);
43
+ // });
44
+ // });
45
+
46
+ // ### The Server Side
47
+
48
+ // If the response is not HTML or XML, you (unfortunately) need to apply some
49
+ // trickery on the server side. To send back a JSON payload, send back an HTML
50
+ // `<textarea>` element with a `data-type` attribute that contains the MIME
51
+ // type, and put the actual payload in the textarea:
52
+
53
+ // <textarea data-type="application/json">
54
+ // {"ok": true, "message": "Thanks so much"}
55
+ // </textarea>
56
+
57
+ // The iframe transport plugin will detect this and attempt to apply the same
58
+ // conversions that jQuery applies to regular responses. That means for the
59
+ // example above you should get a Javascript object as the `data` parameter of
60
+ // the `complete` callback, with the properties `ok: true` and
61
+ // `message: "Thanks so much"`.
62
+
63
+ // ### Compatibility
64
+
65
+ // This plugin has primarily been tested on Safari 5, Firefox 4, and Internet
66
+ // Explorer all the way back to version 6. While I haven't found any issues with
67
+ // it so far, I'm fairly sure it still doesn't work around all the quirks in all
68
+ // different browsers. But the code is still pretty simple overall, so you
69
+ // should be able to fix it and contribute a patch :)
70
+
71
+ // ## Annotated Source
72
+
73
+ (function($, undefined) {
74
+
75
+ // Register a prefilter that checks whether the `iframe` option is set, and
76
+ // switches to the iframe transport if it is `true`.
77
+ $.ajaxPrefilter(function(options, origOptions, jqXHR) {
78
+ if (options.iframe) {
79
+ return "iframe";
80
+ }
81
+ });
82
+
83
+ // Register an iframe transport, independent of requested data type. It will
84
+ // only activate when the "files" option has been set to a non-empty list of
85
+ // enabled file inputs.
86
+ $.ajaxTransport("iframe", function(options, origOptions, jqXHR) {
87
+ var form = null,
88
+ iframe = null,
89
+ origAction = null,
90
+ origTarget = null,
91
+ origEnctype = null,
92
+ addedFields = [],
93
+ disabledFields = [],
94
+ files = $(options.files).filter(":file:enabled");
95
+
96
+ // This function gets called after a successful submission or an abortion
97
+ // and should revert all changes made to the page to enable the
98
+ // submission via this transport.
99
+ function cleanUp() {
100
+ $(addedFields).each(function() {
101
+ this.remove();
102
+ });
103
+ $(disabledFields).each(function() {
104
+ this.disabled = false;
105
+ });
106
+ form.attr("action", origAction || "")
107
+ .attr("target", origTarget || "")
108
+ .attr("enctype", origEnctype || "");
109
+ iframe.attr("src", "javascript:false;").remove();
110
+ }
111
+
112
+ // Remove "iframe" from the data types list so that further processing is
113
+ // based on the content type returned by the server, without attempting an
114
+ // (unsupported) conversion from "iframe" to the actual type.
115
+ options.dataTypes.shift();
116
+
117
+ if (files.length) {
118
+ // Determine the form the file fields belong to, and make sure they all
119
+ // actually belong to the same form.
120
+ files.each(function() {
121
+ if (form !== null && this.form !== form) {
122
+ jQuery.error("All file fields must belong to the same form");
123
+ }
124
+ form = this.form;
125
+ });
126
+ form = $(form);
127
+
128
+ // Store the original form attributes that we'll be replacing temporarily.
129
+ origAction = form.attr("action");
130
+ origTarget = form.attr("target");
131
+ origEnctype = form.attr("enctype");
132
+
133
+ // We need to disable all other inputs in the form so that they don't get
134
+ // included in the submitted data unexpectedly.
135
+ form.find(":input:not(:submit)").each(function() {
136
+ if (!this.disabled && (this.type != "file" || files.index(this) < 0)) {
137
+ this.disabled = true;
138
+ disabledFields.push(this);
139
+ }
140
+ });
141
+
142
+ // If there is any additional data specified via the `data` option,
143
+ // we add it as hidden fields to the form. This (currently) requires
144
+ // the `processData` option to be set to false so that the data doesn't
145
+ // get serialized to a string.
146
+ if (typeof(options.data) === "string" && options.data.length > 0) {
147
+ jQuery.error("data must not be serialized");
148
+ }
149
+ $.each(options.data || {}, function(name, value) {
150
+ if ($.isPlainObject(value)) {
151
+ name = value.name;
152
+ value = value.value;
153
+ }
154
+ addedFields.push($("<input type='hidden'>").attr("name", name)
155
+ .attr("value", value).appendTo(form));
156
+ });
157
+
158
+ // Add a hidden `X-Requested-With` field with the value `IFrame` to the
159
+ // field, to help server-side code to determine that the upload happened
160
+ // through this transport.
161
+ addedFields.push($("<input type='hidden' name='X-Requested-With'>")
162
+ .attr("value", "IFrame").appendTo(form));
163
+
164
+ // Borrowed straight from the JQuery source
165
+ // Provides a way of specifying the accepted data type similar to HTTP_ACCEPTS
166
+ accepts = options.dataTypes[ 0 ] && options.accepts[ options.dataTypes[0] ] ?
167
+ options.accepts[ options.dataTypes[0] ] + ( options.dataTypes[ 0 ] !== "*" ? ", */*; q=0.01" : "" ) :
168
+ options.accepts[ "*" ]
169
+
170
+ addedFields.push($("<input type='hidden' name='X-Http-Accept'>")
171
+ .attr("value", accepts).appendTo(form));
172
+
173
+ return {
174
+
175
+ // The `send` function is called by jQuery when the request should be
176
+ // sent.
177
+ send: function(headers, completeCallback) {
178
+ iframe = $("<iframe src='javascript:false;' name='iframe-" + $.now()
179
+ + "' style='display:none'></iframe>");
180
+
181
+ // The first load event gets fired after the iframe has been injected
182
+ // into the DOM, and is used to prepare the actual submission.
183
+ iframe.bind("load", function() {
184
+
185
+ // The second load event gets fired when the response to the form
186
+ // submission is received. The implementation detects whether the
187
+ // actual payload is embedded in a `<textarea>` element, and
188
+ // prepares the required conversions to be made in that case.
189
+ iframe.unbind("load").bind("load", function() {
190
+
191
+ var doc = this.contentWindow ? this.contentWindow.document :
192
+ (this.contentDocument ? this.contentDocument : this.document),
193
+ root = doc.documentElement ? doc.documentElement : doc.body,
194
+ textarea = root.getElementsByTagName("textarea")[0],
195
+ type = textarea ? textarea.getAttribute("data-type") : null;
196
+
197
+ var status = 200,
198
+ statusText = "OK",
199
+ responses = { text: type ? textarea.value : root ? root.innerHTML : null },
200
+ headers = "Content-Type: " + (type || "text/html")
201
+
202
+ completeCallback(status, statusText, responses, headers);
203
+
204
+ setTimeout(cleanUp, 50);
205
+ });
206
+
207
+ // Now that the load handler has been set up, reconfigure and
208
+ // submit the form.
209
+ form.attr("action", options.url)
210
+ .attr("target", iframe.attr("name"))
211
+ .attr("enctype", "multipart/form-data")
212
+ .get(0).submit();
213
+ });
214
+
215
+ // After everything has been set up correctly, the iframe gets
216
+ // injected into the DOM so that the submission can be initiated.
217
+ iframe.insertAfter(form);
218
+ },
219
+
220
+ // The `abort` function is called by jQuery when the request should be
221
+ // aborted.
222
+ abort: function() {
223
+ if (iframe !== null) {
224
+ iframe.unbind("load").attr("src", "javascript:false;");
225
+ cleanUp();
226
+ }
227
+ }
228
+
229
+ };
230
+ }
231
+ });
232
+
233
+ })(jQuery);