mirror of
https://github.com/github/rails.git
synced 2026-04-26 03:00:59 -04:00
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
This commit is contained in:
@@ -1,5 +1,19 @@
|
||||
*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 @@ module ActionController #:nodoc:
|
||||
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 @@ module ActionController #:nodoc:
|
||||
@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 @@ module ActionView
|
||||
# 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 @@ module ActionView
|
||||
yield
|
||||
record "}, #{(seconds * 1000).to_i})"
|
||||
end
|
||||
|
||||
private
|
||||
def method_missing(method, *arguments, &block)
|
||||
record(@context.send(method, *arguments, &block))
|
||||
|
||||
# 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 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 @@ module ActionView
|
||||
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 @@ class NewRenderTest < Test::Unit::TestCase
|
||||
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 @@ class ScriptaculousHelperTest < Test::Unit::TestCase
|
||||
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" })
|
||||
|
||||
Reference in New Issue
Block a user