actionview 7.0.1 → 7.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (92) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +281 -202
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +3 -3
  5. data/app/assets/javascripts/rails-ujs.esm.js +693 -0
  6. data/app/assets/javascripts/rails-ujs.js +630 -0
  7. data/lib/action_view/base.rb +33 -12
  8. data/lib/action_view/buffers.rb +106 -8
  9. data/lib/action_view/cache_expiry.rb +40 -43
  10. data/lib/action_view/context.rb +1 -1
  11. data/lib/action_view/deprecator.rb +7 -0
  12. data/lib/action_view/digestor.rb +1 -1
  13. data/lib/action_view/gem_version.rb +2 -2
  14. data/lib/action_view/helpers/active_model_helper.rb +1 -1
  15. data/lib/action_view/helpers/asset_tag_helper.rb +133 -48
  16. data/lib/action_view/helpers/asset_url_helper.rb +13 -12
  17. data/lib/action_view/helpers/atom_feed_helper.rb +5 -5
  18. data/lib/action_view/helpers/cache_helper.rb +3 -9
  19. data/lib/action_view/helpers/capture_helper.rb +26 -12
  20. data/lib/action_view/helpers/content_exfiltration_prevention_helper.rb +70 -0
  21. data/lib/action_view/helpers/controller_helper.rb +6 -0
  22. data/lib/action_view/helpers/csp_helper.rb +2 -2
  23. data/lib/action_view/helpers/csrf_helper.rb +3 -3
  24. data/lib/action_view/helpers/date_helper.rb +76 -64
  25. data/lib/action_view/helpers/debug_helper.rb +3 -3
  26. data/lib/action_view/helpers/form_helper.rb +62 -31
  27. data/lib/action_view/helpers/form_options_helper.rb +6 -3
  28. data/lib/action_view/helpers/form_tag_helper.rb +88 -44
  29. data/lib/action_view/helpers/javascript_helper.rb +1 -0
  30. data/lib/action_view/helpers/number_helper.rb +15 -13
  31. data/lib/action_view/helpers/output_safety_helper.rb +4 -4
  32. data/lib/action_view/helpers/rendering_helper.rb +5 -6
  33. data/lib/action_view/helpers/sanitize_helper.rb +34 -15
  34. data/lib/action_view/helpers/tag_helper.rb +27 -16
  35. data/lib/action_view/helpers/tags/base.rb +11 -52
  36. data/lib/action_view/helpers/tags/collection_check_boxes.rb +1 -0
  37. data/lib/action_view/helpers/tags/collection_radio_buttons.rb +1 -0
  38. data/lib/action_view/helpers/tags/collection_select.rb +3 -0
  39. data/lib/action_view/helpers/tags/date_field.rb +1 -1
  40. data/lib/action_view/helpers/tags/date_select.rb +2 -0
  41. data/lib/action_view/helpers/tags/datetime_field.rb +14 -6
  42. data/lib/action_view/helpers/tags/datetime_local_field.rb +11 -2
  43. data/lib/action_view/helpers/tags/grouped_collection_select.rb +3 -0
  44. data/lib/action_view/helpers/tags/month_field.rb +1 -1
  45. data/lib/action_view/helpers/tags/select.rb +4 -1
  46. data/lib/action_view/helpers/tags/select_renderer.rb +56 -0
  47. data/lib/action_view/helpers/tags/time_field.rb +1 -1
  48. data/lib/action_view/helpers/tags/time_zone_select.rb +3 -0
  49. data/lib/action_view/helpers/tags/week_field.rb +1 -1
  50. data/lib/action_view/helpers/tags/weekday_select.rb +3 -0
  51. data/lib/action_view/helpers/tags.rb +2 -0
  52. data/lib/action_view/helpers/text_helper.rb +33 -17
  53. data/lib/action_view/helpers/translation_helper.rb +6 -6
  54. data/lib/action_view/helpers/url_helper.rb +90 -65
  55. data/lib/action_view/helpers.rb +2 -0
  56. data/lib/action_view/layouts.rb +13 -8
  57. data/lib/action_view/log_subscriber.rb +49 -32
  58. data/lib/action_view/lookup_context.rb +29 -13
  59. data/lib/action_view/path_registry.rb +57 -0
  60. data/lib/action_view/path_set.rb +13 -14
  61. data/lib/action_view/railtie.rb +26 -3
  62. data/lib/action_view/record_identifier.rb +16 -9
  63. data/lib/action_view/renderer/abstract_renderer.rb +1 -1
  64. data/lib/action_view/renderer/collection_renderer.rb +9 -1
  65. data/lib/action_view/renderer/partial_renderer/collection_caching.rb +21 -3
  66. data/lib/action_view/renderer/partial_renderer.rb +3 -2
  67. data/lib/action_view/renderer/renderer.rb +2 -0
  68. data/lib/action_view/renderer/streaming_template_renderer.rb +3 -2
  69. data/lib/action_view/renderer/template_renderer.rb +3 -2
  70. data/lib/action_view/rendering.rb +24 -6
  71. data/lib/action_view/ripper_ast_parser.rb +6 -6
  72. data/lib/action_view/routing_url_for.rb +7 -4
  73. data/lib/action_view/template/error.rb +14 -1
  74. data/lib/action_view/template/handlers/builder.rb +4 -4
  75. data/lib/action_view/template/handlers/erb/erubi.rb +23 -27
  76. data/lib/action_view/template/handlers/erb.rb +73 -1
  77. data/lib/action_view/template/handlers.rb +1 -1
  78. data/lib/action_view/template/html.rb +1 -1
  79. data/lib/action_view/template/raw_file.rb +1 -1
  80. data/lib/action_view/template/renderable.rb +1 -1
  81. data/lib/action_view/template/resolver.rb +15 -5
  82. data/lib/action_view/template/text.rb +1 -1
  83. data/lib/action_view/template/types.rb +25 -34
  84. data/lib/action_view/template.rb +227 -53
  85. data/lib/action_view/template_path.rb +2 -0
  86. data/lib/action_view/test_case.rb +174 -21
  87. data/lib/action_view/unbound_template.rb +15 -5
  88. data/lib/action_view/version.rb +1 -1
  89. data/lib/action_view/view_paths.rb +19 -28
  90. data/lib/action_view.rb +4 -1
  91. data/lib/assets/compiled/rails-ujs.js +36 -5
  92. metadata +27 -27
@@ -9,6 +9,9 @@ require "rails-dom-testing"
9
9
 
10
10
  module ActionView
11
11
  # = Action View Test Case
12
+ #
13
+ # Read more about <tt>ActionView::TestCase</tt> in {Testing Rails Applications}[https://guides.rubyonrails.org/testing.html#testing-view-partials]
14
+ # in the guides.
12
15
  class TestCase < ActiveSupport::TestCase
13
16
  class TestController < ActionController::Base
14
17
  include ActionDispatch::TestProcess
@@ -57,9 +60,96 @@ module ActionView
57
60
  include ActiveSupport::Testing::ConstantLookup
58
61
 
59
62
  delegate :lookup_context, to: :controller
60
- attr_accessor :controller, :output_buffer, :rendered
63
+ attr_accessor :controller, :request, :output_buffer
61
64
 
62
65
  module ClassMethods
66
+ def inherited(descendant) # :nodoc:
67
+ super
68
+
69
+ descendant_content_class = content_class.dup
70
+
71
+ if descendant_content_class.respond_to?(:set_temporary_name)
72
+ descendant_content_class.set_temporary_name("rendered_content")
73
+ end
74
+
75
+ descendant.content_class = descendant_content_class
76
+ end
77
+
78
+ # Register a callable to parse rendered content for a given template
79
+ # format.
80
+ #
81
+ # Each registered parser will also define a +#rendered.[FORMAT]+ helper
82
+ # method, where +[FORMAT]+ corresponds to the value of the
83
+ # +format+ argument.
84
+ #
85
+ # === Arguments
86
+ #
87
+ # <tt>format</tt> - Symbol the name of the format used to render view's content
88
+ # <tt>callable</tt> - Callable to parse the String. Accepts the String.
89
+ # value as its only argument.
90
+ # <tt>block</tt> - Block serves as the parser when the
91
+ # <tt>callable</tt> is omitted.
92
+ #
93
+ # By default, ActionView::TestCase defines a parser for:
94
+ #
95
+ # * :html - returns an instance of Nokogiri::XML::Node
96
+ # * :json - returns an instance of ActiveSupport::HashWithIndifferentAccess
97
+ #
98
+ # Each pre-registered parser also defines a corresponding helper:
99
+ #
100
+ # * :html - defines `rendered.html`
101
+ # * :json - defines `rendered.json`
102
+ #
103
+ # === Examples
104
+ #
105
+ # test "renders HTML" do
106
+ # article = Article.create!(title: "Hello, world")
107
+ #
108
+ # render partial: "articles/article", locals: { article: article }
109
+ #
110
+ # assert_pattern { rendered.html.at("main h1") => { content: "Hello, world" } }
111
+ # end
112
+ #
113
+ # test "renders JSON" do
114
+ # article = Article.create!(title: "Hello, world")
115
+ #
116
+ # render formats: :json, partial: "articles/article", locals: { article: article }
117
+ #
118
+ # assert_pattern { rendered.json => { title: "Hello, world" } }
119
+ # end
120
+ #
121
+ # To parse the rendered content into RSS, register a call to <tt>RSS::Parser.parse</tt>:
122
+ #
123
+ # register_parser :rss, -> rendered { RSS::Parser.parse(rendered) }
124
+ #
125
+ # test "renders RSS" do
126
+ # article = Article.create!(title: "Hello, world")
127
+ #
128
+ # render formats: :rss, partial: article
129
+ #
130
+ # assert_equal "Hello, world", rendered.rss.items.last.title
131
+ # end
132
+ #
133
+ # To parse the rendered content into a Capybara::Simple::Node,
134
+ # re-register an <tt>:html</tt> parser with a call to
135
+ # <tt>Capybara.string</tt>:
136
+ #
137
+ # register_parser :html, -> rendered { Capybara.string(rendered) }
138
+ #
139
+ # test "renders HTML" do
140
+ # article = Article.create!(title: "Hello, world")
141
+ #
142
+ # render partial: article
143
+ #
144
+ # rendered.html.assert_css "h1", text: "Hello, world"
145
+ # end
146
+ def register_parser(format, callable = nil, &block)
147
+ parser = callable || block || :itself.to_proc
148
+ content_class.redefine_method(format) do
149
+ parser.call(to_s)
150
+ end
151
+ end
152
+
63
153
  def tests(helper_class)
64
154
  case helper_class
65
155
  when String, Symbol
@@ -105,14 +195,33 @@ module ActionView
105
195
  end
106
196
  end
107
197
 
198
+ included do
199
+ class_attribute :content_class, instance_accessor: false, default: Content
200
+
201
+ setup :setup_with_controller
202
+
203
+ register_parser :html, -> rendered { Rails::Dom::Testing.html_document.parse(rendered).root }
204
+ register_parser :json, -> rendered { JSON.parse(rendered, object_class: ActiveSupport::HashWithIndifferentAccess) }
205
+
206
+ ActiveSupport.run_load_hooks(:action_view_test_case, self)
207
+
208
+ helper do
209
+ def protect_against_forgery?
210
+ false
211
+ end
212
+
213
+ def _test_case
214
+ controller._test_case
215
+ end
216
+ end
217
+ end
218
+
108
219
  def setup_with_controller
109
220
  controller_class = Class.new(ActionView::TestCase::TestController)
110
221
  @controller = controller_class.new
111
222
  @request = @controller.request
112
223
  @view_flow = ActionView::OutputFlow.new
113
- # empty string ensures buffer has UTF-8 encoding as
114
- # new without arguments returns ASCII-8BIT encoded buffer like String#new
115
- @output_buffer = ActiveSupport::SafeBuffer.new ""
224
+ @output_buffer = ActionView::OutputBuffer.new
116
225
  @rendered = +""
117
226
 
118
227
  test_case_instance = self
@@ -133,10 +242,64 @@ module ActionView
133
242
  @_rendered_views ||= RenderedViewsCollection.new
134
243
  end
135
244
 
245
+ # Returns the content rendered by the last +render+ call.
246
+ #
247
+ # The returned object behaves like a string but also exposes a number of methods
248
+ # that allows you to parse the content string in formats registered using
249
+ # <tt>.register_parser</tt>.
250
+ #
251
+ # By default includes the following parsers:
252
+ #
253
+ # +.html+
254
+ #
255
+ # Parse the <tt>rendered</tt> content String into HTML. By default, this means
256
+ # a <tt>Nokogiri::XML::Node</tt>.
257
+ #
258
+ # test "renders HTML" do
259
+ # article = Article.create!(title: "Hello, world")
260
+ #
261
+ # render partial: "articles/article", locals: { article: article }
262
+ #
263
+ # assert_pattern { rendered.html.at("main h1") => { content: "Hello, world" } }
264
+ # end
265
+ #
266
+ # To parse the rendered content into a <tt>Capybara::Simple::Node</tt>,
267
+ # re-register an <tt>:html</tt> parser with a call to
268
+ # <tt>Capybara.string</tt>:
269
+ #
270
+ # register_parser :html, -> rendered { Capybara.string(rendered) }
271
+ #
272
+ # test "renders HTML" do
273
+ # article = Article.create!(title: "Hello, world")
274
+ #
275
+ # render partial: article
276
+ #
277
+ # rendered.html.assert_css "h1", text: "Hello, world"
278
+ # end
279
+ #
280
+ # +.json+
281
+ #
282
+ # Parse the <tt>rendered</tt> content String into JSON. By default, this means
283
+ # a <tt>ActiveSupport::HashWithIndifferentAccess</tt>.
284
+ #
285
+ # test "renders JSON" do
286
+ # article = Article.create!(title: "Hello, world")
287
+ #
288
+ # render formats: :json, partial: "articles/article", locals: { article: article }
289
+ #
290
+ # assert_pattern { rendered.json => { title: "Hello, world" } }
291
+ # end
292
+ def rendered
293
+ @_rendered ||= self.class.content_class.new(@rendered)
294
+ end
295
+
136
296
  def _routes
137
297
  @controller._routes if @controller.respond_to?(:_routes)
138
298
  end
139
299
 
300
+ class Content < SimpleDelegator
301
+ end
302
+
140
303
  # Need to experiment if this priority is the best one: rendered => output_buffer
141
304
  class RenderedViewsCollection
142
305
  def initialize
@@ -163,25 +326,10 @@ module ActionView
163
326
  end
164
327
  end
165
328
 
166
- included do
167
- setup :setup_with_controller
168
- ActiveSupport.run_load_hooks(:action_view_test_case, self)
169
-
170
- helper do
171
- def protect_against_forgery?
172
- false
173
- end
174
-
175
- def _test_case
176
- controller._test_case
177
- end
178
- end
179
- end
180
-
181
329
  private
182
330
  # Need to experiment if this priority is the best one: rendered => output_buffer
183
331
  def document_root_element
184
- Nokogiri::HTML::Document.parse(@rendered.blank? ? @output_buffer : @rendered).root
332
+ Rails::Dom::Testing.html_document.parse(@rendered.blank? ? @output_buffer.to_str : @rendered).root
185
333
  end
186
334
 
187
335
  module Locals
@@ -227,6 +375,10 @@ module ActionView
227
375
  :@_result,
228
376
  :@_routes,
229
377
  :@controller,
378
+ :@_controller,
379
+ :@_request,
380
+ :@_config,
381
+ :@_default_form_builder,
230
382
  :@_layouts,
231
383
  :@_files,
232
384
  :@_rendered_views,
@@ -245,7 +397,7 @@ module ActionView
245
397
  :@view_context_class,
246
398
  :@view_flow,
247
399
  :@_subscribers,
248
- :@html_document
400
+ :@html_document,
249
401
  ]
250
402
 
251
403
  def _user_defined_ivars
@@ -277,6 +429,7 @@ module ActionView
277
429
  super
278
430
  end
279
431
  end
432
+ ruby2_keywords(:method_missing)
280
433
 
281
434
  def respond_to_missing?(name, include_private = false)
282
435
  begin
@@ -18,21 +18,31 @@ module ActionView
18
18
  end
19
19
 
20
20
  def bind_locals(locals)
21
- if template = @templates[locals]
22
- template
23
- else
21
+ unless template = @templates[locals]
24
22
  @write_lock.synchronize do
25
23
  normalized_locals = normalize_locals(locals)
26
24
 
27
25
  # We need ||=, both to dedup on the normalized locals and to check
28
26
  # while holding the lock.
29
- @templates[normalized_locals] ||= build_template(normalized_locals)
27
+ template = (@templates[normalized_locals] ||= build_template(normalized_locals))
30
28
 
31
29
  # This may have already been assigned, but we've already de-dup'd so
32
30
  # reassignment is fine.
33
- @templates[locals.dup] = @templates[normalized_locals]
31
+ @templates[locals.dup] = template
32
+
33
+ if template.strict_locals?
34
+ # Under strict locals, we only need one template.
35
+ # This replaces the @templates Concurrent::Map with a hash which
36
+ # returns this template for every key.
37
+ @templates = Hash.new(template).freeze
38
+ end
34
39
  end
35
40
  end
41
+ template
42
+ end
43
+
44
+ def built_templates # :nodoc:
45
+ @templates.values
36
46
  end
37
47
 
38
48
  private
@@ -3,7 +3,7 @@
3
3
  require_relative "gem_version"
4
4
 
5
5
  module ActionView
6
- # Returns the version of the currently loaded ActionView as a <tt>Gem::Version</tt>
6
+ # Returns the currently loaded version of Action View as a +Gem::Version+.
7
7
  def self.version
8
8
  gem_version
9
9
  end
@@ -5,7 +5,7 @@ module ActionView
5
5
  extend ActiveSupport::Concern
6
6
 
7
7
  included do
8
- ViewPaths.set_view_paths(self, ActionView::PathSet.new.freeze)
8
+ ActionView::PathRegistry.set_view_paths(self, ActionView::PathSet.new.freeze)
9
9
  end
10
10
 
11
11
  delegate :template_exists?, :any_templates?, :view_paths, :formats, :formats=,
@@ -13,11 +13,11 @@ module ActionView
13
13
 
14
14
  module ClassMethods
15
15
  def _view_paths
16
- ViewPaths.get_view_paths(self)
16
+ ActionView::PathRegistry.get_view_paths(self)
17
17
  end
18
18
 
19
19
  def _view_paths=(paths)
20
- ViewPaths.set_view_paths(self, paths)
20
+ ActionView::PathRegistry.set_view_paths(self, paths)
21
21
  end
22
22
 
23
23
  def _prefixes # :nodoc:
@@ -28,6 +28,13 @@ module ActionView
28
28
  end
29
29
  end
30
30
 
31
+ def _build_view_paths(paths) # :nodoc:
32
+ return paths if ActionView::PathSet === paths
33
+
34
+ paths = ActionView::PathRegistry.cast_file_system_resolvers(paths)
35
+ ActionView::PathSet.new(paths)
36
+ end
37
+
31
38
  # Append a path to the list of view paths for this controller.
32
39
  #
33
40
  # ==== Parameters
@@ -35,7 +42,7 @@ module ActionView
35
42
  # the default view path. You may also provide a custom view path
36
43
  # (see ActionView::PathSet for more information)
37
44
  def append_view_path(path)
38
- self._view_paths = view_paths + Array(path)
45
+ self._view_paths = view_paths + _build_view_paths(path)
39
46
  end
40
47
 
41
48
  # Prepend a path to the list of view paths for this controller.
@@ -45,7 +52,7 @@ module ActionView
45
52
  # the default view path. You may also provide a custom view path
46
53
  # (see ActionView::PathSet for more information)
47
54
  def prepend_view_path(path)
48
- self._view_paths = ActionView::PathSet.new(Array(path) + view_paths)
55
+ self._view_paths = _build_view_paths(path) + view_paths
49
56
  end
50
57
 
51
58
  # A list of all of the default view paths for this controller.
@@ -59,7 +66,7 @@ module ActionView
59
66
  # * <tt>paths</tt> - If a PathSet is provided, use that;
60
67
  # otherwise, process the parameter into a PathSet.
61
68
  def view_paths=(paths)
62
- self._view_paths = ActionView::PathSet.new(Array(paths))
69
+ self._view_paths = _build_view_paths(paths)
63
70
  end
64
71
 
65
72
  private
@@ -70,30 +77,14 @@ module ActionView
70
77
  end
71
78
  end
72
79
 
73
- # :stopdoc:
74
- @all_view_paths = {}
75
-
76
- def self.get_view_paths(klass)
77
- @all_view_paths[klass] || get_view_paths(klass.superclass)
78
- end
79
-
80
- def self.set_view_paths(klass, paths)
81
- @all_view_paths[klass] = paths
82
- end
83
-
84
- def self.all_view_paths
85
- @all_view_paths.values.uniq
86
- end
87
- # :startdoc:
88
-
89
80
  # The prefixes used in render "foo" shortcuts.
90
81
  def _prefixes # :nodoc:
91
82
  self.class._prefixes
92
83
  end
93
84
 
94
- # <tt>LookupContext</tt> is the object responsible for holding all
85
+ # LookupContext is the object responsible for holding all
95
86
  # information required for looking up templates, i.e. view paths and
96
- # details. Check <tt>ActionView::LookupContext</tt> for more information.
87
+ # details. Check ActionView::LookupContext for more information.
97
88
  def lookup_context
98
89
  @_lookup_context ||=
99
90
  ActionView::LookupContext.new(self.class._view_paths, details_for_lookup, _prefixes)
@@ -103,24 +94,24 @@ module ActionView
103
94
  {}
104
95
  end
105
96
 
106
- # Append a path to the list of view paths for the current <tt>LookupContext</tt>.
97
+ # Append a path to the list of view paths for the current LookupContext.
107
98
  #
108
99
  # ==== Parameters
109
100
  # * <tt>path</tt> - If a String is provided, it gets converted into
110
101
  # the default view path. You may also provide a custom view path
111
102
  # (see ActionView::PathSet for more information)
112
103
  def append_view_path(path)
113
- lookup_context.view_paths.push(*path)
104
+ lookup_context.append_view_paths(self.class._build_view_paths(path))
114
105
  end
115
106
 
116
- # Prepend a path to the list of view paths for the current <tt>LookupContext</tt>.
107
+ # Prepend a path to the list of view paths for the current LookupContext.
117
108
  #
118
109
  # ==== Parameters
119
110
  # * <tt>path</tt> - If a String is provided, it gets converted into
120
111
  # the default view path. You may also provide a custom view path
121
112
  # (see ActionView::PathSet for more information)
122
113
  def prepend_view_path(path)
123
- lookup_context.view_paths.unshift(*path)
114
+ lookup_context.prepend_view_paths(self.class._build_view_paths(path))
124
115
  end
125
116
  end
126
117
  end
data/lib/action_view.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  #--
4
- # Copyright (c) 2004-2022 David Heinemeier Hansson
4
+ # Copyright (c) David Heinemeier Hansson
5
5
  #
6
6
  # Permission is hereby granted, free of charge, to any person obtaining
7
7
  # a copy of this software and associated documentation files (the
@@ -26,7 +26,9 @@
26
26
  require "active_support"
27
27
  require "active_support/rails"
28
28
  require "action_view/version"
29
+ require "action_view/deprecator"
29
30
 
31
+ # :include: actionview/README.rdoc
30
32
  module ActionView
31
33
  extend ActiveSupport::Autoload
32
34
 
@@ -39,6 +41,7 @@ module ActionView
39
41
  autoload :Helpers
40
42
  autoload :LookupContext
41
43
  autoload :Layouts
44
+ autoload :PathRegistry
42
45
  autoload :PathSet
43
46
  autoload :RecordIdentifier
44
47
  autoload :Rendering
@@ -73,6 +73,22 @@ Released under the MIT license
73
73
  return element[expando][key] = value;
74
74
  };
75
75
 
76
+ Rails.isContentEditable = function(element) {
77
+ var isEditable;
78
+ isEditable = false;
79
+ while (true) {
80
+ if (element.isContentEditable) {
81
+ isEditable = true;
82
+ break;
83
+ }
84
+ element = element.parentElement;
85
+ if (!element) {
86
+ break;
87
+ }
88
+ }
89
+ return isEditable;
90
+ };
91
+
76
92
  Rails.$ = function(selector) {
77
93
  return Array.prototype.slice.call(document.querySelectorAll(selector));
78
94
  };
@@ -395,9 +411,9 @@ Released under the MIT license
395
411
 
396
412
  }).call(this);
397
413
  (function() {
398
- var disableFormElement, disableFormElements, disableLinkElement, enableFormElement, enableFormElements, enableLinkElement, formElements, getData, isXhrRedirect, matches, setData, stopEverything;
414
+ var disableFormElement, disableFormElements, disableLinkElement, enableFormElement, enableFormElements, enableLinkElement, formElements, getData, isContentEditable, isXhrRedirect, matches, setData, stopEverything;
399
415
 
400
- matches = Rails.matches, getData = Rails.getData, setData = Rails.setData, stopEverything = Rails.stopEverything, formElements = Rails.formElements;
416
+ matches = Rails.matches, getData = Rails.getData, setData = Rails.setData, stopEverything = Rails.stopEverything, formElements = Rails.formElements, isContentEditable = Rails.isContentEditable;
401
417
 
402
418
  Rails.handleDisabledElement = function(e) {
403
419
  var element;
@@ -417,6 +433,9 @@ Released under the MIT license
417
433
  } else {
418
434
  element = e;
419
435
  }
436
+ if (isContentEditable(element)) {
437
+ return;
438
+ }
420
439
  if (matches(element, Rails.linkDisableSelector)) {
421
440
  return enableLinkElement(element);
422
441
  } else if (matches(element, Rails.buttonDisableSelector) || matches(element, Rails.formEnableSelector)) {
@@ -429,6 +448,9 @@ Released under the MIT license
429
448
  Rails.disableElement = function(e) {
430
449
  var element;
431
450
  element = e instanceof Event ? e.target : e;
451
+ if (isContentEditable(element)) {
452
+ return;
453
+ }
432
454
  if (matches(element, Rails.linkDisableSelector)) {
433
455
  return disableLinkElement(element);
434
456
  } else if (matches(element, Rails.buttonDisableSelector) || matches(element, Rails.formDisableSelector)) {
@@ -513,10 +535,12 @@ Released under the MIT license
513
535
 
514
536
  }).call(this);
515
537
  (function() {
516
- var stopEverything;
538
+ var isContentEditable, stopEverything;
517
539
 
518
540
  stopEverything = Rails.stopEverything;
519
541
 
542
+ isContentEditable = Rails.isContentEditable;
543
+
520
544
  Rails.handleMethod = function(e) {
521
545
  var csrfParam, csrfToken, form, formContent, href, link, method;
522
546
  link = this;
@@ -524,6 +548,9 @@ Released under the MIT license
524
548
  if (!method) {
525
549
  return;
526
550
  }
551
+ if (isContentEditable(this)) {
552
+ return;
553
+ }
527
554
  href = Rails.href(link);
528
555
  csrfToken = Rails.csrfToken();
529
556
  csrfParam = Rails.csrfParam();
@@ -545,10 +572,10 @@ Released under the MIT license
545
572
 
546
573
  }).call(this);
547
574
  (function() {
548
- var ajax, fire, getData, isCrossDomain, isRemote, matches, serializeElement, setData, stopEverything,
575
+ var ajax, fire, getData, isContentEditable, isCrossDomain, isRemote, matches, serializeElement, setData, stopEverything,
549
576
  slice = [].slice;
550
577
 
551
- matches = Rails.matches, getData = Rails.getData, setData = Rails.setData, fire = Rails.fire, stopEverything = Rails.stopEverything, ajax = Rails.ajax, isCrossDomain = Rails.isCrossDomain, serializeElement = Rails.serializeElement;
578
+ matches = Rails.matches, getData = Rails.getData, setData = Rails.setData, fire = Rails.fire, stopEverything = Rails.stopEverything, ajax = Rails.ajax, isCrossDomain = Rails.isCrossDomain, serializeElement = Rails.serializeElement, isContentEditable = Rails.isContentEditable;
552
579
 
553
580
  isRemote = function(element) {
554
581
  var value;
@@ -566,6 +593,10 @@ Released under the MIT license
566
593
  fire(element, 'ajax:stopped');
567
594
  return false;
568
595
  }
596
+ if (isContentEditable(element)) {
597
+ fire(element, 'ajax:stopped');
598
+ return false;
599
+ }
569
600
  withCredentials = element.getAttribute('data-with-credentials');
570
601
  dataType = element.getAttribute('data-type') || 'script';
571
602
  if (matches(element, Rails.formSubmitSelector)) {