Responds to Parent

In the pursuit of AJAX file uploads, I ran into the pattern of posting a form to a hidden IFRAME returning javascript control back to the parent page to display a progress bar, make visual effects, show a “uploading” graphic or basically do anything than the default blocking of the page until the upload is finished.

Just give me the plugin.

With Rails and RJS, I wanted an easy way to maintain my page update logic without having to worry (too much) about where that code was being executed. This follows the iframe remoting pattern.

Taking the pragmatic approach, we just create an IFRAME in our page to accept the form, target the form to the IFRAME, then in our controller’s form action, we return javascript to be evaluated in the parent window. Easy as that. Here’s the example:

Controller:

  class Test < ActionController::Base
    def main
    end

    def form_action
      # Do stuff with params[:uploaded_file]

      responds_to_parent do
        render :update do |page|
          page << "alert($('stuff').innerHTML)"
        end
      end
    end
  end

main.rhtml:

<html>
    <body>
      <div id="stuff">Here is some stuff</div>

      <form target="frame" action="form_action">
        <input type="file" name="uploaded_file"/>
        <input type="submit"/>
      </form>

      <iframe id='frame' name="frame"></iframe>
    </body>
  </html>

All we did was wrap the render :update block with a responds_to_parent block. Now your RJS update executes in the parent window rather than in the IFRAME.

Tested environments:

  • Safari 2.0.3
  • Firefox 1.5.0
  • IE 6
  • Opera 8.52, 9b2 (Thanks Julio Cesar Ody for the fix!)

Extra:

18 responses to “Responds to Parent”

12 12 2007
In-place file upload with Ruby on Rails || Dmytro Shteflyuk’s Home (04:33:01) :

[...] and it’s implementation as Ruby on Rails plugin here. Example of using: class TestController < ActionController::Base   def upload_action   [...]

16 01 2008
Bhe Bautista (00:14:56) :

I’m having problem with respond_to_parent plugin in Safari3. The page.replace_html(Element.update()) doesn’t work. It’s fine in Safari 2 but it crashes in Safari 3.

21 01 2008
Richard (03:27:07) :

Seems to not be working in Safari 3, what is the problem here? Are you planning to upgrade with a fix to this? I get the following error

RJS error: TypeError: Value undefined (result of expression Element.update) is not object.

Many thanks

21 01 2008
streadway (08:34:05) :

I will try to fix then when time permits, but that may be a while. I’ll happily apply any patches that fix this, so if you would like to investigate a little bit, I know many that will be grateful.

23 01 2008
Yuval Kordov (16:55:07) :

Hi Sean. Fabulous plugin that has enabled me to do all the client-side form error handling I wanted to do when uploading. However, as stated above, I have also run into problems with Safari 3. I provided a detailed example here. Please let me know if you need any more specific info. Cheers.

13 02 2008
WEBtudinho v. 2.0 - » Upload de arquivos com AJAX em Ruby on Rails (09:28:38) :

[...] lidar com o formulário no servidor, utilizaremos o plugin responds_to_parent: script/plugin install [...]

20 02 2008
Cid Dennis (03:23:45) :

Is there a way to access both the parent and the iframe. So for example I could do some work in the iframe and still update the parent at the same time?

Thanks

20 02 2008
streadway (17:25:09) :

Sorry, but the iframe is just a workaround and was intended to not be used as anything other than to make the browser behave asynchronously. So nope, just the parent is intended to be used. If you wish work with another iframe then include that in the parent frame.

11 03 2008
Rafael Mueller (18:33:31) :

The “Just give me the plugin.” isnt working, 404 error

Regards

11 03 2008
streadway (21:39:54) :

Good catch Rafael. The link now heads on over to Google Code.

3 04 2008
25 04 2008
Peter T. Brown (17:57:38) :

BTW, this tends to fail in Rails 2.0.2 with the error:

/sw/lib/ruby/gems/1.8/gems/activesupport-2.0.2-/lib/active_support/dependencies.rb:376:in `new_constants_in’: You have a nil object when you didn’t expect it! (NoMethodError)
You might have expected an instance of Array.
The error occurred while evaluating nil.empty? from /sw/lib/ruby/gems/1.8/gems/activesupport-2.0.2-/lib/active_support/dependencies.rb:202:in `load_file’

To fix, you’ve got to add to the top of init.rb:

require ‘responds_to_parent’

7 05 2008
A Fresh Cup » Blog Archive » Double Shot #202 (11:52:55) :

[...] Responds to Parent - This may be another bit required to get multi-file uploads working: a way to send AJAX responses back from an IFRAME to its parent. [...]

23 05 2008
Double Shot #202 | Developer Home (18:31:55) :

[...] Responds to Parent - This may be another bit required to get multi-file uploads working: a way to send AJAX responses back from an IFRAME to its parent. [...]

11 06 2008
17 07 2008
Zone of Mr. Frosti » Blog Archive » Adventures with Rails: Part Quatre (03:59:03) :

[...] Targeted Announcement editor complete with TinyMCE (the rich-text editor), AJAX file uploads (using responds_to_parent), and Javascript live form validation. The real showcase here is outside of the Rails platform, [...]

4 08 2008
kin (21:39:10) :

I’m getting an error when responds_to_parent is called.


uncaught exception: Permission denied to get property Window.setTimeout

This happens every time, and sometimes I get this:


uncaught exception: Permission denied to get property Window.setTimeout
getIframeSize()adfetch (line 26)
onload(load )

I believe it’s coming from this chunk of code in responds_to_parent.rb:


# Eval in parent scope and replace document location of this frame
# so back button doesn't replay action on targeted forms
# loc = document.location to be set after parent is updated for IE
# with(window.parent) - pull in variables from parent window
# setTimeout - scope the execution in the windows parent for safari
# window.eval - legal eval for Opera
render :text => "
var loc = document.location;
with(window.parent) { setTimeout(function() { window.eval('#{script}'); loc.replace('about:blank'); }, 1) }
"

Any ideas why this might be happening?

4 08 2008
Apotomo Cookbook » Blog Archive » Apotomo can upload files with AJAX! (23:14:09) :

[...] this work-around in Rails is quite expensive, an example can be found here. This example uses the responds_to_parent plugin. I’m glad people found a railish solution and released it, but I really dislike the [...]

Leave a comment

You can use these tags : <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>