提交 9c52a412 编写于 作者: S Sam Stephenson

Add the ability to call JavaScriptGenerator methods from helpers called in update blocks

git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@3476 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
上级 185cca23
*SVN*
* Add the ability to call JavaScriptGenerator methods from helpers called in update blocks. [Sam Stephenson] Example:
module ApplicationHelper
def update_time
page.replace_html 'time', Time.now.to_s(:db)
page.visual_effect :highlight, 'time'
end
end
class UserController < ApplicationController
def poll
render :update { |page| page.update_time }
end
end
* Add render(:update) to ActionView::Base. [Sam Stephenson]
* Fix render(:update) to not render layouts. [Sam Stephenson]
......
......@@ -687,7 +687,7 @@ def render_text(text = nil, status = nil)
end
def render_javascript(javascript, status = nil)
@response.headers['Content-type'] = 'text/javascript'
@response.headers['Content-Type'] = 'text/javascript'
render_text(javascript, status)
end
......@@ -719,7 +719,8 @@ def erase_render_results
@response.body = nil
@performed_render = false
end
# Clears the redirected results from the headers, resets the status to 200 and returns
# the URL that was used to redirect or nil if there was no redirected URL
# Note that +redirect_to+ will change the body of the response to indicate a redirection.
......
......@@ -370,34 +370,52 @@ def observe_form(form_id, options = {})
# this in your Ajax response bodies, either in a <script> tag or as plain
# JavaScript sent with a Content-type of "text/javascript".
#
# Create new instances with PrototypeHelper#update_page, then call
# #insert_html, #replace_html, #remove, #show, or #hide on the yielded
# generator in any order you like to modify the content and appearance of
# the current page. (You can also call other helper methods which
# return JavaScript, such as
# ActionView::Helpers::ScriptaculousHelper#visual_effect.)
# Create new instances with PrototypeHelper#update_page or with
# ActionController::Base#render, then call #insert_html, #replace_html,
# #remove, #show, #hide, #visual_effect, or any other of the built-in
# methods on the yielded generator in any order you like to modify the
# content and appearance of the current page.
#
# Example:
#
# update_page do |page|
# page.insert_html :bottom, 'list', '<li>Last item</li>'
# page.insert_html :bottom, 'list', "<li>#{@item.name}</li>"
# page.visual_effect :highlight, 'list'
# page.hide 'status-indicator', 'cancel-link'
# end
#
# generates the following JavaScript:
#
# new Insertion.Bottom("list", "<li>Last item</li>");
# new Insertion.Bottom("list", "<li>Some item</li>");
# new Effect.Highlight("list");
# ["status-indicator", "cancel-link"].each(Element.hide);
#
# Helper methods can be used in conjunction with JavaScriptGenerator.
# When a helper method is called inside an update block on the +page+
# object, that method will also have access to a +page+ object.
#
# Example:
#
# module ApplicationHelper
# def update_time
# page.replace_html 'time', Time.now.to_s(:db)
# page.visual_effect :highlight, 'time'
# end
# end
#
# # Controller action
# def poll
# render :update { |page| page.update_time }
# end
#
# You can also use PrototypeHelper#update_page_tag instead of
# PrototypeHelper#update_page to wrap the generated JavaScript in a
# <script> tag.
class JavaScriptGenerator
def initialize(context) #:nodoc:
def initialize(context, &block) #:nodoc:
@context, @lines = context, []
yield self
include_helpers_from_context
@context.instance_exec(self, &block)
end
def to_s #:nodoc:
......@@ -501,12 +519,24 @@ def delay(seconds = 1)
yield
record "}, #{(seconds * 1000).to_i})"
end
# Starts a Scriptaculous visual effect. See
# ActionView::Helpers::ScriptaculousHelper for more information.
def visual_effect(name, id, options = {})
record @context.send(:visual_effect, name, id, options)
end
private
def method_missing(method, *arguments, &block)
record(@context.send(method, *arguments, &block))
def include_helpers_from_context
@context.extended_by.each do |mod|
extend mod unless mod.name =~ /^ActionView::Helpers/
end
end
def page
self
end
def record(line)
returning line = "#{line.to_s.chomp.gsub /\;$/, ''};" do
self << line
......
......@@ -52,23 +52,6 @@ def visual_effect(name, element_id = false, js_options = {})
end
end
# Needs more work so + isn't required for concation of effects. Currently, you have to do:
#
# page.parallel_effects do
# page.visual_effect(:highlight, 'dom_id') +
# page.visual_effect(:fade, 'dom_id')
# end
#
# ...naturally, it would be better just to do
#
# page.parallel_effects do
# page.visual_effect :highlight, 'dom_id'
# page.visual_effect :fade, 'dom_id'
# end
def parallel_effects(js_options = {}) #:nodoc:
"new Effect.Parallel([" + yield + "], #{options_for_javascript(js_options)})"
end
# Makes the element with the DOM ID specified by +element_id+ sortable
# by drag-and-drop and make an Ajax call whenever the sort order has
# changed. By default, the action called gets the serialized sortable
......
......@@ -490,7 +490,7 @@ def test_render_text_with_assigns
def test_update_page
get :update_page
assert_template nil
assert_equal 'text/javascript', @response.headers['Content-type']
assert_equal 'text/javascript', @response.headers['Content-Type']
assert_equal 2, @response.body.split($/).length
end
......
......@@ -40,15 +40,6 @@ def test_toggle_effects
end
def test_parallel_effects
actual = parallel_effects(:duration => 2) do
visual_effect(:highlight, "posts") +
visual_effect(:fade, "fademe", :duration => 4.0)
end
assert_equal "new Effect.Parallel([new Effect.Highlight('posts',{});new Effect.Fade('fademe',{duration:4.0});], {duration:2})", actual
end
def test_sortable_element
assert_dom_equal %(<script type=\"text/javascript\">\n//<![CDATA[\nSortable.create('mylist', {onUpdate:function(){new Ajax.Request('http://www.example.com/order', {asynchronous:true, evalScripts:true, parameters:Sortable.serialize('mylist')})}})\n//]]>\n</script>),
sortable_element("mylist", :url => { :action => "order" })
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册