Permalink
Browse files

responds_to_parent for rails 3

  • Loading branch information...
1 parent a93adb5 commit 8f849b71b22e37a664266cdb8d456e71cdf6a5a8 Sandip Ransing committed Feb 11, 2011
@@ -5,38 +5,43 @@ Adds responds_to_parent to your controller to respond to the parent document of
Make Ajaxy file uploads by posting the form to a hidden iframe, and respond with
RJS to the parent window.
+http://sean.treadway.info/responds-to-parent/
+
+
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>
-
+
+
+Copyright (c) 2006 Sean Treadway, released under the MIT license
@@ -1,2 +1 @@
ActionController::Base.send :include, RespondsToParent
-require 'parent_selector_assertion'
@@ -0,0 +1 @@
+# Install hook code here
@@ -1,144 +0,0 @@
-module ActionController
- module Assertions
- module SelectorAssertions
- # :call-seq:
- # assert_select_parent()
- # assert_select_parent() { |script| ... }
- #
- # Selects JavaScript that is generated for the `parent' window.
- #
- # Without a block, #assert_select_parent asserts that the response
- # is generated by responds_to_parent.
- #
- # With a block, #assert_select_parent selects script that is supposed
- # to be evaluated in the parent window and passes it to the block.
- # Typically #assert_select_rjs is used in the block.
- def assert_select_parent(*args, &block)
- wrapper_re_str = Regexp.escape("with(window.parent) { setTimeout(function() { window.eval('") +
- "(.*)" +
- Regexp.escape("'); loc.replace('about:blank'); }, 1) }")
- match = @response.body.match(Regexp.new(wrapper_re_str))
-
- if match
- escaped_js = match[1]
- unescaped_js = escaped_js.
- gsub(%r!</scr"\+"ipt>!, '</script>').
- gsub(/\\(\'|\")/, '\1').
- gsub(/((?:^|[^\\])(?:\\\\)*)\\n/, "\\1\n"). # replace `n' with odd number of backslash.
- gsub(/\\\\/, '\\')
- @response.body = unescaped_js # assert_select_rjs refers @response.body.
-
- if block_given?
- begin
- in_scope, @selected = @selected, unescaped_js
- yield unescaped_js
- ensure
- @selected = in_scope
- end
- end
- unescaped_js
- else
- # doesn't seem a responds_to_parent content.
- flunk args.shift || "No content for the parent window."
- end
- end
- end
- end
-end
-
-module ActionController
- module Assertions
- module SelectorAssertions
- # :call-seq:
- # assert_select_parent()
- # assert_select_parent() { |script| ... }
- #
- # Selects JavaScript that is generated for the `parent' window.
- #
- # Without a block, #assert_select_parent asserts that the response
- # is generated by responds_to_parent.
- #
- # With a block, #assert_select_parent selects script that is supposed
- # to be evaluated in the parent window and passes it to the block.
- # Typically #assert_select_rjs is used in the block.
- def assert_select_parent(*args, &block)
- wrapper_re_str = Regexp.escape("with(window.parent) { setTimeout(function() { window.eval('") +
- "(.*)" +
- Regexp.escape("'); loc.replace('about:blank'); }, 1) }")
- match = @response.body.match(Regexp.new(wrapper_re_str))
-
- if match
- escaped_js = match[1]
- unescaped_js = escaped_js.
- gsub(%r!</scr"\+"ipt>!, '</script>').
- gsub(/\\(\'|\")/, '\1').
- gsub(/((?:^|[^\\])(?:\\\\)*)\\n/, "\\1\n"). # replace `n' with odd number of backslash.
- gsub(/\\\\/, '\\')
- @response.body = unescaped_js # assert_select_rjs refers @response.body.
-
- if block_given?
- begin
- in_scope, @selected = @selected, unescaped_js
- yield unescaped_js
- ensure
- @selected = in_scope
- end
- end
- unescaped_js
- else
- # doesn't seem a responds_to_parent content.
- flunk args.shift || "No content for the parent window."
- end
- end
- end
- end
-end
-
-module ActionController
- module Assertions
- module SelectorAssertions
- # :call-seq:
- # assert_select_parent()
- # assert_select_parent() { |script| ... }
- #
- # Selects JavaScript that is generated for the `parent' window.
- #
- # Without a block, #assert_select_parent asserts that the response
- # is generated by responds_to_parent.
- #
- # With a block, #assert_select_parent selects script that is supposed
- # to be evaluated in the parent window and passes it to the block.
- # Typically #assert_select_rjs is used in the block.
- def assert_select_parent(*args, &block)
- wrapper_re_str = Regexp.escape("with(window.parent) { setTimeout(function() { window.eval('") +
- "(.*)" +
- Regexp.escape("'); loc.replace('about:blank'); }, 1) }")
- match = @response.body.match(Regexp.new(wrapper_re_str))
-
- if match
- escaped_js = match[1]
- unescaped_js = escaped_js.
- gsub(%r!</scr"\+"ipt>!, '</script>').
- gsub(/\\(\'|\")/, '\1').
- gsub(/((?:^|[^\\])(?:\\\\)*)\\n/, "\\1\n"). # replace `n' with odd number of backslash.
- gsub(/\\\\/, '\\')
- @response.body = unescaped_js # assert_select_rjs refers @response.body.
-
- if block_given?
- begin
- in_scope, @selected = @selected, unescaped_js
- yield unescaped_js
- ensure
- @selected = in_scope
- end
- end
- unescaped_js
- else
- # doesn't seem a responds_to_parent content.
- flunk args.shift || "No content for the parent window."
- end
- end
- end
- end
-end
-
@@ -1,23 +1,47 @@
+# Copyright (c) 2006 Sean Treadway
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+
# Module containing the methods useful for child IFRAME to parent window communication
module RespondsToParent
-
+
# Executes the response body as JavaScript in the context of the parent window.
# Use this method of you are posting a form to a hidden IFRAME or if you would like
# to use IFRAME base RPC.
def responds_to_parent(&block)
yield
-
+
if performed?
# We're returning HTML instead of JS or XML now
response.headers['Content-Type'] = 'text/html; charset=UTF-8'
-
+
# Either pull out a redirect or the request body
- script = if location = erase_redirect_results
+ script = if response.headers['Location']
+ #TODO: erase_redirect_results is missing in rails 3.0 has to be implemented
+# erase redirect
"document.location.href = #{location.to_s.inspect}"
else
response.body
end
-
+
# Escape quotes, linebreaks and slashes, maintaining previously escaped slashes
# Suggestions for improvement?
script = (script || '').
@@ -27,18 +51,18 @@ def responds_to_parent(&block)
gsub('</script>','</scr"+"ipt>')
# Clear out the previous render to prevent double render
- erase_results
-
- # Eval in parent scope and replace document location of this frame
+ response.request.env['action_controller.instance'].instance_variable_set(:@_response_body, nil)
+
+ # 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 => "<html><body><script type='text/javascript' charset='utf-8'>
var loc = document.location;
- with(window.parent) { setTimeout(function() { window.eval('#{script}'); loc.replace('about:blank'); }, 1) }
- </script></body></html>"
+ with(window.parent) { setTimeout(function() { window.eval('#{script}'); if (typeof(loc) !== 'undefined') loc.replace('about:blank'); }, 1) };
+ </script></body></html>".html_safe
end
end
alias respond_to_parent responds_to_parent
Oops, something went wrong.

0 comments on commit 8f849b7

Please sign in to comment.