Ruby on Rails | Screencasts | Download | Documentation | Weblog | Community | Source

Ticket #3876: prototype_helpers.fixed.diff

File prototype_helpers.fixed.diff, 16.5 kB (added by rick, 3 years ago)

fixed issue with chained visual_effects call

  • activesupport/test/json.rb

    old new  
    99end 
    1010 
    1111class TestJSONEmitters < Test::Unit::TestCase 
    12   TrueTests    = [[ true,  %(true)  ]] 
    13   FalseTests   = [[ false, %(false) ]] 
    14   NilTests     = [[ nil,   %(null)  ]] 
    15   NumericTests = [[ 1,     %(1)     ], 
    16                   [ 2.5,   %(2.5)   ]] 
     12  TrueTests     = [[ true,  %(true)  ]] 
     13  FalseTests    = [[ false, %(false) ]] 
     14  NilTests      = [[ nil,   %(null)  ]] 
     15  NumericTests  = [[ 1,     %(1)     ], 
     16                   [ 2.5,   %(2.5)   ]] 
    1717                     
    18   StringTests  = [[ 'this is the string',     %("this is the string")         ], 
    19                   [ 'a "string" with quotes', %("a \\"string\\" with quotes") ]] 
     18  StringTests   = [[ 'this is the string',     %("this is the string")         ], 
     19                   [ 'a "string" with quotes', %("a \\"string\\" with quotes") ]] 
    2020                  
    21   ArrayTests   = [[ ['a', 'b', 'c'],          %([\"a\", \"b\", \"c\"])          ], 
    22                   [ [1, 'a', :b, nil, false], %([1, \"a\", \"b\", null, false]) ]] 
     21  ArrayTests    = [[ ['a', 'b', 'c'],          %([\"a\", \"b\", \"c\"])          ], 
     22                   [ [1, 'a', :b, nil, false], %([1, \"a\", \"b\", null, false]) ]] 
    2323   
    24   HashTests    = [[ {:a => :b, :c => :d}, %({\"c\": \"d\", \"a\": \"b\"}) ]] 
     24  HashTests     = [[ {:a => :b, :c => :d}, %({\"c\": \"d\", \"a\": \"b\"}) ]] 
    2525                   
    26   SymbolTests  = [[ :a,     %("a")    ], 
    27                   [ :this,  %("this") ], 
    28                   [ :"a b", %("a b")  ]] 
     26  SymbolTests   = [[ :a,     %("a")    ], 
     27                   [ :this,  %("this") ], 
     28                   [ :"a b", %("a b")  ]] 
    2929 
    30   ObjectTests  = [[ Foo.new(1, 2), %({\"a\": 1, \"b\": 2}) ]] 
    31    
     30  ObjectTests   = [[ Foo.new(1, 2), %({\"a\": 1, \"b\": 2}) ]] 
     31 
     32  VariableTests = [[ ActiveSupport::JSON::Variable.new('foo'), 'foo'], 
     33                   [ ActiveSupport::JSON::Variable.new('alert("foo")'), 'alert("foo")']] 
     34  RegexpTests   = [[ /^a/, '/^a/' ], /^\w{1,2}[a-z]+/ix, '/^\\w{1,2}[a-z]+/ix'] 
     35 
    3236  constants.grep(/Tests$/).each do |class_tests| 
    3337    define_method("test_#{class_tests[0..-6].downcase}") do 
    3438      self.class.const_get(class_tests).each do |pair| 
  • activesupport/lib/active_support/json/encoders/core.rb

    old new  
    5656          result << '}' 
    5757        end 
    5858      end 
     59 
     60      define_encoder Regexp do |regexp| 
     61        regexp.inspect 
     62      end 
    5963    end 
    6064  end 
    6165end 
  • activesupport/lib/active_support/json.rb

    old new  
    33module ActiveSupport 
    44  module JSON #:nodoc: 
    55    class CircularReferenceError < StandardError; end 
    6        
     6    # returns the literal string as its JSON encoded form.  Useful for passing javascript variables into functions. 
     7    # 
     8    # page.call 'Element.show', ActiveSupport::JSON::Variable.new("$$(#items li)") 
     9    class Variable < String 
     10      def to_json 
     11        self 
     12      end 
     13    end 
     14 
    715    class << self 
    816      REFERENCE_STACK_VARIABLE = :json_reference_stack 
    917       
  • actionpack/test/template/prototype_helper_test.rb

    old new  
    33module BaseTest 
    44  include ActionView::Helpers::JavaScriptHelper 
    55  include ActionView::Helpers::PrototypeHelper 
     6  include ActionView::Helpers::ScriptaculousHelper 
    67   
    78  include ActionView::Helpers::UrlHelper 
    89  include ActionView::Helpers::TagHelper 
     
    147148  end 
    148149end 
    149150 
     151ActionView::Helpers::JavaScriptCollectionProxy.send :public, :enumerate 
     152 
    150153class JavaScriptGeneratorTest < Test::Unit::TestCase 
    151154  include BaseTest 
    152155   
     
    234237 
    235238  def test_element_proxy_one_deep 
    236239    @generator['hello'].hide 
    237     assert_equal %($('hello').hide();), @generator.to_s 
     240    assert_equal %(Element.hide("hello");), @generator.to_s 
    238241  end 
    239242 
    240243  def test_element_proxy_assignment 
     
    243246  end 
    244247 
    245248  def test_element_proxy_two_deep 
    246     @generator['hello'].hide("first").display 
    247     assert_equal %($('hello').hide("first").display();), @generator.to_s 
     249    @generator['hello'].hide("first").visual_effect(:highlight) 
     250    assert_equal %(Element.hide("hello", "first");\nnew Effect.Highlight('hello',{});), @generator.to_s 
    248251  end 
    249    
     252 
     253  def test_element_proxy_visual_effect 
     254    @generator['hello'].visual_effect :highlight 
     255    assert_equal %(new Effect.Highlight('hello',{});), @generator.to_s 
     256  end 
     257 
     258  def test_element_proxy_visual_effect_with_options 
     259    @generator['hello'].visual_effect :highlight, :duration => 0.4 
     260    assert_equal %(new Effect.Highlight('hello',{duration:0.4});), @generator.to_s 
     261  end 
     262 
    250263  def test_select_access 
    251264    assert_equal %($$('div.hello');), @generator.select('div.hello') 
    252265  end 
    253266 
    254267  def test_select_proxy_one_deep 
    255268    @generator.select('p.welcome b').first.hide 
    256     assert_equal %($$('p.welcome b').first().hide();), @generator.to_s 
     269    assert_equal %(Element.hide($$('p.welcome b').first());), @generator.to_s 
    257270  end 
     271 
     272  def test_select_proxy_two_deep 
     273    @generator.select('p.welcome b').first('a').hide.show 
     274    assert_equal %(a = $$('p.welcome b').first();\nElement.hide(a);\nElement.show(a);), @generator.to_s 
     275  end 
     276 
     277  def test_collection_proxy_with_each 
     278    @generator.select('p.welcome b').each do |page, value| 
     279      value.remove_class_name 'selected' 
     280    end 
     281    @generator.select('p.welcome b').each do |page, value, index| 
     282      page.call 'alert', index 
     283      page.call 'alert', value, 'selected' 
     284    end 
     285      assert_equal <<-EOS.strip, @generator.to_s 
     286$$('p.welcome b').each(function(value, index) { 
     287Element.removeClassName(value, "selected"); 
     288}); 
     289$$('p.welcome b').each(function(value, index) { 
     290alert(index); 
     291alert(value, "selected"); 
     292}); 
     293      EOS 
     294  end 
     295 
     296  def test_collection_proxy_on_enumerables_with_return_and_index 
     297    iterator            = Proc.new { |page, value|        page << '(value.className == "welcome")' } 
     298    iterator_with_index = Proc.new { |page, value, index| page.call 'alert', index ; page << '(value.className == "welcome")' } 
     299    ActionView::Helpers::JavaScriptCollectionProxy::ENUMERABLE_METHODS_WITH_RETURN.each do |enum| 
     300      @generator.select('p').enumerate(enum, 'a', &iterator) 
     301      @generator.select('p').enumerate(enum, 'b', &iterator_with_index) 
     302       
     303      assert_equal <<-EOS.strip, @generator.to_s 
     304a = $$('p').#{enum}(function(value, index) { 
     305return (value.className == "welcome"); 
     306}); 
     307b = $$('p').#{enum}(function(value, index) { 
     308alert(index); 
     309return (value.className == "welcome"); 
     310}); 
     311      EOS 
     312      @generator = create_generator 
     313    end 
     314  end 
     315 
     316  def test_collection_proxy_with_grep 
     317    @generator.select('p').grep 'a', /^a/ do |page, value| 
     318      page << '(value.className == "welcome")' 
     319    end 
     320    @generator.select('p').grep 'b', /b$/ do |page, value, index| 
     321      page.call 'alert', value 
     322      page << '(value.className == "welcome")' 
     323    end 
     324 
     325    assert_equal <<-EOS.strip, @generator.to_s 
     326a = $$('p').grep(/^a/, function(value, index) { 
     327return (value.className == "welcome"); 
     328}); 
     329b = $$('p').grep(/b$/, function(value, index) { 
     330alert(value); 
     331return (value.className == "welcome"); 
     332}); 
     333    EOS 
     334  end 
     335 
     336  def test_collection_proxy_with_inject 
     337    @generator.select('p').inject 'a', [] do |page, memo, value| 
     338      page << '(value.className == "welcome")' 
     339    end 
     340    @generator.select('p').inject 'b', nil do |page, memo, value, index| 
     341      memo.hide.show 
     342      page << '(value.className == "welcome")' 
     343    end 
     344 
     345    assert_equal <<-EOS.strip, @generator.to_s 
     346a = $$('p').inject([], function(memo, value, index) { 
     347return (value.className == "welcome"); 
     348}); 
     349b = $$('p').inject(null, function(memo, value, index) { 
     350Element.hide(memo); 
     351Element.show(memo); 
     352return (value.className == "welcome"); 
     353}); 
     354    EOS 
     355  end 
     356 
     357  def test_collection_proxy_with_pluck 
     358    @generator.select('p').pluck('a', 'className') 
     359    assert_equal %(a = $$('p').pluck("className");), @generator.to_s 
     360  end 
     361 
     362  def test_collection_proxy_with_zip 
     363    ActionView::Helpers::JavaScriptCollectionProxy.new(@generator, '[1, 2, 3]').zip('a', [4, 5, 6], [7, 8, 9]) 
     364    ActionView::Helpers::JavaScriptCollectionProxy.new(@generator, '[1, 2, 3]').zip('b', [4, 5, 6], [7, 8, 9]) do |page, array| 
     365      page.call 'array.reverse' 
     366    end 
     367 
     368    assert_equal <<-EOS.strip, @generator.to_s 
     369a = [1, 2, 3].zip([4, 5, 6], [7, 8, 9]); 
     370b = [1, 2, 3].zip([4, 5, 6], [7, 8, 9], function(array) { 
     371return array.reverse(); 
     372}); 
     373    EOS 
     374  end 
    258375end 
  • actionpack/lib/action_view/helpers/prototype_helper.rb

    old new  
    421421        # used for further method calls. Examples: 
    422422        # 
    423423        #   page['blank_slate']                  # => $('blank_slate'); 
    424         #   page['blank_slate'].show             # => $('blank_slate').show(); 
    425         #   page['blank_slate'].show('first').up # => $('blank_slate').show('first').up(); 
     424        #   page['blank_slate'].show             # => Element.show("blank_slate"); 
     425        #   page['blank_slate'].show('first').up # => Element.show("blank_slate", "first"); Element.up("blank_slate"); 
    426426        def [](id) 
    427427          JavaScriptElementProxy.new(self, id) 
    428428        end 
     
    430430        # Returns a collection reference by finding it through a CSS +pattern+ in the DOM. This collection can then be 
    431431        # used for further method calls. Examples: 
    432432        # 
    433         #   page.select('p')                      # => $$('p'); 
    434         #   page.select('p.welcome b').first      # => $$('p.welcome b').first(); 
    435         #   page.select('p.welcome b').first.hide # => $$('p.welcome b').first().hide(); 
     433        #   page.select('p')                                # => $$('p'); 
     434        #   page.select('p.welcome b').first                # => $$('p.welcome b').first(); 
     435        #   page.select('p.welcome b').first.hide           # => Element.hide($$('p.welcome b').first()); 
     436        #   page.select('p.welcome b').first('a').hide.show # => a = $$('p.welcome b').first(); Element.hide(a); Element.show(a); 
    436437        def select(pattern) 
    437           JavaScriptCollectionProxy.new(self, pattern) 
     438          JavaScriptElementCollectionProxy.new(self, pattern) 
    438439        end 
    439440   
    440441        # Inserts HTML at the specified +position+ relative to the DOM element 
     
    595596        end 
    596597 
    597598        def javascript_object_for(object) 
    598           object.respond_to?(:to_json) ? object.to_json : object.inspect 
     599          object.to_json rescue object.inspect 
    599600        end 
    600601 
    601602        def arguments_for_call(arguments) 
     
    667668 
    668669    # Converts chained method calls on DOM proxy elements into JavaScript chains  
    669670    class JavaScriptProxy < Builder::BlankSlate #:nodoc: 
    670       def initialize(generator, root
     671      def initialize(generator, root = nil
    671672        @generator = generator 
    672         @generator << root 
     673        @generator << root if root 
    673674      end 
    674675 
    675676      private 
     
    687688        end 
    688689 
    689690        def assign(variable, value) 
    690           append_to_function_chain! "#{variable} = #{@generator.send(:javascript_object_for, value)}" 
     691          append_to_function_chain!("#{variable} = #{@generator.send(:javascript_object_for, value)}") 
    691692        end 
    692693         
    693694        def function_chain 
     
    695696        end 
    696697         
    697698        def append_to_function_chain!(call) 
    698           function_chain[-1] = function_chain[-1][0..-2] if function_chain[-1][-1..-1] == ";" # strip last ; 
    699           function_chain[-1] += ".#{call};" 
     699          if function_chain.any? 
     700            function_chain[-1].chomp!(";") # strip last ; 
     701            function_chain[-1] += ".#{call};" 
     702          else 
     703            function_chain.push("#{call};") 
     704          end 
    700705        end 
    701706    end 
    702707     
    703708    class JavaScriptElementProxy < JavaScriptProxy #:nodoc: 
    704709      def initialize(generator, id) 
    705710        @id = id 
    706         super(generator, "$('#{id}')"
     711        super(generator
    707712      end 
    708        
     713 
    709714      def replace_html(*options_for_render) 
    710715        call 'update', @generator.send(:render, *options_for_render) 
    711716      end 
     
    717722      def reload 
    718723        replace :partial => @id.to_s 
    719724      end 
     725 
     726      def to_json 
     727        @id.to_json 
     728      end 
     729 
     730      def visual_effect(name, options = {}) 
     731        @generator << @generator.visual_effect(name, @id, options) 
     732        self 
     733      end 
     734 
     735      private 
     736        def method_missing(method, *arguments) 
     737          if method.to_s =~ /(.*)=$/ 
     738            @generator << "$('#{@id}')" 
     739            super 
     740          else 
     741            @generator.call "Element.#{method.to_s.first}#{method.to_s.classify[1..-1]}", @id, *arguments 
     742            self 
     743          end 
     744        end 
    720745    end 
    721746 
    722747    class JavaScriptCollectionProxy < JavaScriptProxy #:nodoc: 
     748      ENUMERABLE_METHODS_WITH_RETURN = [:all, :any, :collect, :map, :detect, :find, :findAll, :select, :max, :min, :partition, :reject, :sortBy] 
     749 
    723750      def initialize(generator, pattern) 
    724         @pattern = pattern 
    725         super(generator, "$$('#{pattern}')") 
     751        super(generator, @pattern = pattern) 
    726752      end 
    727753 
    728       # TODO: Implement funky stuff like .each 
     754      def grep(variable, pattern, &block) 
     755        enumerable_method("grep(#{pattern.to_json}, function(value, index) {", variable, %w(value index), &block) 
     756      end 
     757 
     758      def inject(variable, memo, &block) 
     759        enumerable_method("inject(#{memo.to_json}, function(memo, value, index) {", variable, %w(memo value index), &block) 
     760      end 
     761 
     762      def pluck(variable, property) 
     763        add_variable_assignment!(variable) 
     764        append_enumerable_function!("pluck(#{property.to_json});") 
     765      end 
     766 
     767      def zip(variable, *arguments, &block) 
     768        add_variable_assignment!(variable) 
     769        append_enumerable_function!("zip(#{arguments.collect { |a| a.to_json } * ', '}") 
     770        if block 
     771          function_chain[-1] += ", function(array) {" 
     772          yield @generator, ActiveSupport::JSON::Variable.new('array') 
     773          add_return_statement! 
     774          @generator << '});' 
     775        else 
     776          function_chain[-1] += ');' 
     777        end 
     778      end 
     779 
     780      def each(&block) 
     781        enumerate('each', nil, &block) 
     782      end 
     783 
     784      ENUMERABLE_METHODS_WITH_RETURN.each do |meth_name| 
     785        define_method(meth_name) do 
     786          enumerate(meth_name, true, &block) 
     787        end 
     788      end 
     789 
     790      [:first, :last].each do |meth_name|  
     791        define_method(meth_name) do |*variables| 
     792          variable = variables.first 
     793          call(meth_name) 
     794          add_variable_assignment!(variable) if variable 
     795          JavaScriptElementProxy.new(@generator, ActiveSupport::JSON::Variable.new(variable || function_chain.pop.chomp(';'))) 
     796        end 
     797      end 
     798       
     799      private 
     800        def enumerate(enumerable, variable = nil, &block) 
     801          enumerable_method("#{enumerable}(function(value, index) {", variable, %w(value index), &block) 
     802        end 
     803 
     804        def enumerable_method(enumerable, variable, yield_params, &block) 
     805          add_variable_assignment!(variable) if variable 
     806          append_enumerable_function!(enumerable) 
     807          yield *([@generator] + yield_params.collect { |p| JavaScriptElementProxy.new(@generator, ActiveSupport::JSON::Variable.new(p)) }) 
     808          add_return_statement! if variable 
     809          @generator << '});' 
     810        end 
     811 
     812        def add_variable_assignment!(variable) 
     813          function_chain.push("#{variable} = #{function_chain.pop}") 
     814        end 
     815 
     816        def add_return_statement! 
     817          unless function_chain.last =~ /return/ 
     818            function_chain.push("return #{function_chain.pop.chomp(';')};") 
     819          end 
     820        end 
     821         
     822        def append_enumerable_function!(call) 
     823          append_to_function_chain!(call) 
     824          function_chain[-1].chomp!(";") # strip last ; 
     825        end 
    729826    end 
     827     
     828    class JavaScriptElementCollectionProxy < JavaScriptCollectionProxy #:nodoc:\ 
     829      def initialize(generator, pattern) 
     830        super(generator, "$$('#{pattern}')") 
     831      end 
     832    end 
    730833  end 
    731834end