From 6fa8f81d7d730527f92d8e373dfc32199799681b Mon Sep 17 00:00:00 2001 From: Bob Remeika Date: Thu, 24 Sep 2009 00:18:52 -0700 Subject: Took another stab at observe_field. Now implementing data only helpers as script elements. --- actionpack/lib/action_view/helpers/ajax_helper.rb | 52 ++++++++++++++++++----- actionpack/test/javascript/ajax_test.rb | 51 ++++++++++++---------- 2 files changed, 69 insertions(+), 34 deletions(-) diff --git a/actionpack/lib/action_view/helpers/ajax_helper.rb b/actionpack/lib/action_view/helpers/ajax_helper.rb index 6a13bcb432..43856acbc8 100644 --- a/actionpack/lib/action_view/helpers/ajax_helper.rb +++ b/actionpack/lib/action_view/helpers/ajax_helper.rb @@ -34,21 +34,51 @@ module ActionView tag(:input, html_options) end - def observe_field(name, options = {}, html_options = {}) - url = options.delete(:url) - url = url_for(url) if url.is_a?(Hash) + def observe_field(name, options = {}) + if options[:url] + options[:url] = options[:url].is_a?(Hash) ? url_for(options[:url]) : options[:url] + end + + if options[:frequency] + case options[:frequency] + when 0 + options.delete(:frequency) + else + options[:frequency] = options[:frequency].to_i + end + end + + if options[:with] && (options[:with] !~ /[\{=(.]/) + options[:with] = "'#{options[:with]}=' + encodeURIComponent(value)" + else + options[:with] ||= 'value' unless options[:function] + end - frequency = options.delete(:frequency) - if frequency && frequency > 0 - html_options[:"data-frequency"] = frequency + if options[:function] + statements = options[:function] # || remote_function(options) # TODO: Need to implement remote function - BR + options[:function] = JSFunction.new(statements, "element", "value") end - html_options.merge!(:style => "display:none", - :"data-observe-field" => name, - :"data-observe" => true, - :"data-url" => url) + options[:name] = name + + <<-SCRIPT + + SCRIPT + end - tag(:div, html_options) + # TODO: Move to javascript helpers - BR + class JSFunction + def initialize(statements, *arguments) + @statements, @arguments = statements, arguments + end + + def as_json(options = nil) + "function(#{@arguments.join(", ")}) {#{@statements}}" + end end module Rails2Compatibility diff --git a/actionpack/test/javascript/ajax_test.rb b/actionpack/test/javascript/ajax_test.rb index e46e346d79..97a69ba732 100644 --- a/actionpack/test/javascript/ajax_test.rb +++ b/actionpack/test/javascript/ajax_test.rb @@ -112,6 +112,8 @@ class ButtonToRemoteTest < AjaxTestCase end end +# TODO: We need a better way to test JSON being returned from data only helpers - BR +# TODO: We might also need a lower level data only helper method??? - BR class ObserveFieldTest < AjaxTestCase def protect_against_forgery? false @@ -123,46 +125,49 @@ class ObserveFieldTest < AjaxTestCase test "basic" do assert_html field, - %w(div style="display:none" data-observe="true" data-observe-field="title") + %w(script type="application/json" data-rails-type="observe_field") end test "using a url string" do assert_html field(:url => "/some/other/url"), - %w(data-url="/some/other/url") + %w("url":"/some/other/url") end test "using a url hash" do assert_html field(:url => {:controller => :blog, :action => :update}), - %w(data-url="/url/hash") + %w("url":"/url/hash") end - test "with a :frequency option" do + test "using a :frequency option" do assert_html field(:frequency => 5.minutes), - %w(data-frequency="300") + %w("frequency":300) end - test "with a :frequency option of 0" do - assert_no_match /data-frequency/, field(:frequency => 0) + test "using a :frequency option of 0" do + assert_no_match /frequency/, field(:frequency => 0) end + # TODO: Finish when remote_function or some equivilent is finished -BR # def test_observe_field # assert_dom_equal %(), # observe_field("glass", :frequency => 5.minutes, :url => { :action => "reorder_if_empty" }) # end -# -# def test_observe_field_using_with_option -# expected = %() -# assert_dom_equal expected, observe_field("glass", :frequency => 5.minutes, :url => { :action => "check_value" }, :with => 'id') -# assert_dom_equal expected, observe_field("glass", :frequency => 5.minutes, :url => { :action => "check_value" }, :with => "'id=' + encodeURIComponent(value)") -# end -# -# def test_observe_field_using_json_in_with_option -# expected = %() -# assert_dom_equal expected, observe_field("glass", :frequency => 5.minutes, :url => { :action => "check_value" }, :with => "{'id':value}") -# end -# -# def test_observe_field_using_function_for_callback -# assert_dom_equal %(), -# observe_field("glass", :frequency => 5.minutes, :function => "alert('Element changed')") -# end + + # TODO: Consider using JSON instead of strings. Is using 'value' as a magical reference to the value of the observed field weird? (Rails2 does this) - BR + test "using a :with option" do + assert_html field(:with => "foo"), + %w("with":"'foo=' + encodeURIComponent(value)") + assert_html field(:with => "'foo=' + encodeURIComponent(value)"), + %w("with":"'foo=' + encodeURIComponent(value)") + end + + test "using json in a :with option" do + assert_html field(:with => "{'id':value}"), + %w("with":"{'id':value}") + end + + test "using :function for callback" do + assert_html field(:function => "alert('Element changed')"), + %w("function":"function(element, value) {alert('Element changed')}") + end end -- cgit v1.2.3