diff options
author | Sam Stephenson <sam@37signals.com> | 2006-10-19 22:03:27 +0000 |
---|---|---|
committer | Sam Stephenson <sam@37signals.com> | 2006-10-19 22:03:27 +0000 |
commit | 351a224d90d5d485cb30743f1266ec2624ae7853 (patch) | |
tree | c29ff0df75b03db11dcfac6f2d95df233399d066 /actionpack | |
parent | dbd0bd5e5c9946ffb48bf8651f81ebc6dd9b52e5 (diff) | |
download | rails-351a224d90d5d485cb30743f1266ec2624ae7853.tar.gz rails-351a224d90d5d485cb30743f1266ec2624ae7853.tar.bz2 rails-351a224d90d5d485cb30743f1266ec2624ae7853.zip |
Add support for converting blocks into function arguments in JavaScriptGenerator#call and JavaScriptProxy#call.
Add JavaScriptGenerator#literal for wrapping a string in an object whose #to_json is the string itself.
git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@5323 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
Diffstat (limited to 'actionpack')
-rw-r--r-- | actionpack/CHANGELOG | 4 | ||||
-rw-r--r-- | actionpack/lib/action_view/helpers/prototype_helper.rb | 47 | ||||
-rw-r--r-- | actionpack/test/template/prototype_helper_test.rb | 27 |
3 files changed, 65 insertions, 13 deletions
diff --git a/actionpack/CHANGELOG b/actionpack/CHANGELOG index 05f2328f7d..655f91d1bb 100644 --- a/actionpack/CHANGELOG +++ b/actionpack/CHANGELOG @@ -1,5 +1,9 @@ *SVN* +* Add support for converting blocks into function arguments to JavaScriptGenerator#call and JavaScriptProxy#call. [Sam Stephenson] + +* Add JavaScriptGenerator#literal for wrapping a string in an object whose #to_json is the string itself. [Sam Stephenson] + * Add <%= escape_once html %> to escape html while leaving any currently escaped entities alone. Fix button_to double-escaping issue. [Rick] * Fix double-escaped entities, such as &amp;, &#123;, etc. [Rick] diff --git a/actionpack/lib/action_view/helpers/prototype_helper.rb b/actionpack/lib/action_view/helpers/prototype_helper.rb index f1b956cf12..1b4d2e71d8 100644 --- a/actionpack/lib/action_view/helpers/prototype_helper.rb +++ b/actionpack/lib/action_view/helpers/prototype_helper.rb @@ -458,6 +458,12 @@ module ActionView JavaScriptElementProxy.new(self, id) end + # Returns an object whose <tt>#to_json</tt> evaluates to +code+. Use this to pass a literal JavaScript + # expression as an argument to another JavaScriptGenerator method. + def literal(code) + JavaScriptLiteral.new(code) + end + # Returns a collection reference by finding it through a CSS +pattern+ in the DOM. This collection can then be # used for further method calls. Examples: # @@ -578,16 +584,18 @@ module ActionView call 'alert', message end - # Redirects the browser to the given +location+, in the same form as - # +url_for+. + # Redirects the browser to the given +location+, in the same form as +url_for+. def redirect_to(location) assign 'window.location.href', @context.url_for(location) end - # Calls the JavaScript +function+, optionally with the given - # +arguments+. - def call(function, *arguments) - record "#{function}(#{arguments_for_call(arguments)})" + # Calls the JavaScript +function+, optionally with the given +arguments+. + # + # If a block is given, the block will be passed to a new JavaScriptGenerator; + # the resulting JavaScript code will then be wrapped inside <tt>function() { ... }</tt> + # and passed as the called function's final argument. + def call(function, *arguments, &block) + record "#{function}(#{arguments_for_call(arguments, block)})" end # Assigns the JavaScript +variable+ the given +value+. @@ -649,7 +657,7 @@ module ActionView end def record(line) - returning line = "#{line.to_s.chomp.gsub /\;$/, ''};" do + returning line = "#{line.to_s.chomp.gsub(/\;\z/, '')};" do self << line end end @@ -664,10 +672,16 @@ module ActionView object.respond_to?(:to_json) ? object.to_json : object.inspect end - def arguments_for_call(arguments) + def arguments_for_call(arguments, block = nil) + arguments << block_to_function(block) if block arguments.map { |argument| javascript_object_for(argument) }.join ', ' end + def block_to_function(block) + generator = self.class.new(@context, &block) + literal("function() { #{generator.to_s} }") + end + def method_missing(method, *arguments) JavaScriptProxy.new(self, method.to_s.camelize) end @@ -744,6 +758,13 @@ module ActionView end end + # Bypasses string escaping so you can pass around raw JavaScript + class JavaScriptLiteral < String #:nodoc: + def to_json + to_s + end + end + # Converts chained method calls on DOM proxy elements into JavaScript chains class JavaScriptProxy < Builder::BlankSlate #:nodoc: def initialize(generator, root = nil) @@ -752,16 +773,16 @@ module ActionView end private - def method_missing(method, *arguments) + def method_missing(method, *arguments, &block) if method.to_s =~ /(.*)=$/ assign($1, arguments.first) else - call("#{method.to_s.camelize(:lower)}", *arguments) + call("#{method.to_s.camelize(:lower)}", *arguments, &block) end end - def call(function, *arguments) - append_to_function_chain!("#{function}(#{@generator.send(:arguments_for_call, arguments)})") + def call(function, *arguments, &block) + append_to_function_chain!("#{function}(#{@generator.send(:arguments_for_call, arguments, block)})") self end @@ -770,7 +791,7 @@ module ActionView end def function_chain - @function_chain ||= @generator.instance_variable_get("@lines") + @function_chain ||= @generator.instance_variable_get(:@lines) end def append_to_function_chain!(call) diff --git a/actionpack/test/template/prototype_helper_test.rb b/actionpack/test/template/prototype_helper_test.rb index a88d0f7c9f..0364ceea62 100644 --- a/actionpack/test/template/prototype_helper_test.rb +++ b/actionpack/test/template/prototype_helper_test.rb @@ -448,10 +448,37 @@ return (value.className == "welcome"); ensure ActionView::Base.debug_rjs = false end + + def test_literal + literal = @generator.literal("function() {}") + assert_equal "function() {}", literal.to_json + assert_equal "", @generator.to_s + end def test_class_proxy @generator.form.focus('my_field') assert_equal "Form.focus(\"my_field\");", @generator.to_s end + + def test_call_with_block + @generator.call(:before) + @generator.call(:my_method) do |p| + p[:one].show + p[:two].hide + end + @generator.call(:in_between) + @generator.call(:my_method_with_arguments, true, "hello") do |p| + p[:three].visual_effect(:highlight) + end + assert_equal "before();\nmy_method(function() { $(\"one\").show();\n$(\"two\").hide(); });\nin_between();\nmy_method_with_arguments(true, \"hello\", function() { $(\"three\").visualEffect(\"highlight\"); });", @generator.to_s + end + + def test_class_proxy_call_with_block + @generator.my_object.my_method do |p| + p[:one].show + p[:two].hide + end + assert_equal "MyObject.myMethod(function() { $(\"one\").show();\n$(\"two\").hide(); });", @generator.to_s + end end |