aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack/lib/action_view/helpers/javascript_helper.rb
blob: d072546a63bc06fbda43b63c6d55fb3b1bdca35d (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
require File.dirname(__FILE__) + '/tag_helper'

module ActionView
  module Helpers
    # You must call <%= define_javascript_functions %> in your application before using these helpers.
    module JavascriptHelper
      def link_to_toggle_display(name, tags, html_options = {})
        html_options.symbolize_keys!
        toggle_functions = [ tags ].flatten.collect { |tag| "toggle_display_by_id('#{tag}'); " }.join
        content_tag(
          "a", name, 
          html_options.merge(:href => "#", :onclick => "#{toggle_functions}#{html_options[:onclick]}; return false;")
        )
      end
  
      def link_to_function(name, function, html_options = {})
        content_tag(
          "a", name, 
          html_options.symbolize_keys.merge(:href => "#", :onclick => "#{function}; return false;")
        )
      end

      def link_to_remote(name, options = {})  
        link_to_function(name, remote_function(options))
      end

      def form_remote_tag(options = {})
        options[:form] = true

        options[:html] ||= { }
        options[:html][:onsubmit] = "#{remote_function(options)}; return false;"

        tag("form", options[:html], true)
      end

      def define_javascript_functions
    <<-EOF
    <script language="JavaScript">
    /* XMLHttpRequest Methods */

    function update_with_response() {
      o(arguments[0]).innerHTML = xml_request(arguments[1], arguments[2]);
    }

    function xml_request() {
      var url        = arguments[0];
      var parameters = arguments[1];
      var async      = arguments[2];
      var type       = parameters ? "POST" : "GET";

      req = xml_http_request_object();
      req.open(type, url, async);
      req.send(parameters);

      return req.responseText;
    }

    function xml_http_request_object() {
      var req = false;
      try {
        req = new ActiveXObject("Msxml2.XMLHTTP");
      } catch (e) {
        try {
          req = new ActiveXObject("Microsoft.XMLHTTP");
        } catch (E) {
          req = false;
        }
      }

      if (!req && typeof XMLHttpRequest!='undefined') {
        req = new XMLHttpRequest();
      }

      return req;
    }


    /* Common methods ------------------------------ */

    function toggle_display_by_id(id) {
      o(id).style.display = (o(id).style.display == "none") ? "" : "none";
    }

    function o(id) {
      return document.getElementById(id);
    }


    /* Serialize a form by Sam Stephenson ------------------------------ */

    Form = {
      Serializers: {
        input: function(element) {
          switch (element.type.toLowerCase()) {
            case 'hidden':
            case 'text':
              return Form.Serializers.textarea(element);
            case 'checkbox':  
            case 'radio':
              return Form.Serializers.inputSelector(element);
          }
        },
    
        inputSelector: function(element) {
          if (element.checked)
            return [element.name, element.value];
        },
    
        textarea: function(element) {
          return [element.name, element.value];
        },
    
        select: function(element) {
          var index = element.selectedIndex;
          return [element.name, element.options[index].value];
        }
      },
  
      serialize: function(form) {
        var elements = Form.getFormElements(form);
        var queryComponents = new Array();
    
        for (var i = 0; i < elements.length; i++) {
          var element = elements[i];
          var method = element.tagName.toLowerCase();
      
          var parameter = Form.Serializers[method](element);
          if (parameter) {
            var queryComponent = encodeURIComponent(parameter[0]) + '=' +
                                 encodeURIComponent(parameter[1]);
            queryComponents.push(queryComponent);
          }
        }
    
        return queryComponents.join('&');
      },
  
      getFormElements: function(form) {
        var elements = new Array();
        for (tagName in Form.Serializers) {
          var tagElements = form.getElementsByTagName(tagName);
          for (var j = 0; j < tagElements.length; j++)
            elements.push(tagElements[j]);
        }
        return elements;
      }
    }
    </script>
    EOF
      end

      private
        def remote_function(options)
          function = options[:update] ? 
            "update_with_response('#{options[:update]}', '#{url_for(options[:url])}'#{', Form.serialize(this)' if options[:form]})" :
            "xml_request('#{url_for(options[:url])}'#{', Form.serialize(this)' if options[:form]})"

          function = "#{options[:before]};#{function}" if options[:before]
          function = "#{function};#{options[:after]}"  if options[:after]
      
          return function
        end
    end
  end
end