Skip to content
Newer
Older
100644 157 lines (147 sloc) 6.5 KB
76f024a @fxn adds missing requires for Object#blank? and Object#present?
fxn authored
1 require 'active_support/core_ext/object/blank'
330327e @spastorino Call html_escape in ERB::Util module and don't mix it in in the helpers
spastorino authored
2 require 'active_support/core_ext/string/output_safety'
e2c49e6 @jeremy Drop a string conversion from the often-called tag_options helper
jeremy authored
3 require 'set'
db045db @dhh Initial
dhh authored
4
5 module ActionView
324de19 @rizwanreza Added titles and description.
rizwanreza authored
6 # = Action View Tag Helpers
730c8e8 @technoweenie Clean up multiple calls to #stringify_keys in TagHelper, add better d…
technoweenie authored
7 module Helpers #:nodoc:
b00e6a9 @dhh Massive documentation update for all helpers (closes #8223, #8177, #8175
dhh authored
8 # Provides methods to generate HTML tags programmatically when you can't use
730c8e8 @technoweenie Clean up multiple calls to #stringify_keys in TagHelper, add better d…
technoweenie authored
9 # a Builder. By default, they output XHTML compliant tags.
db045db @dhh Initial
dhh authored
10 module TagHelper
4464b8e Deprecate block_called_from_erb? pending a solution for getting it in…
Carlhuda authored
11 extend ActiveSupport::Concern
12 include CaptureHelper
13
d860c89 @marclove Fix tag helpers so that all HTML element boolean attributes render ac…
marclove authored
14 BOOLEAN_ATTRIBUTES = %w(disabled readonly multiple checked autobuffer
15 autoplay controls loop selected hidden scoped async
16 defer reversed ismap seemless muted required
17 autofocus novalidate formnovalidate open).to_set
80ae74d @tilsammans Prevent any warnings from being printed during RDoc generation
tilsammans authored
18 BOOLEAN_ATTRIBUTES.merge(BOOLEAN_ATTRIBUTES.map {|attribute| attribute.to_sym })
8fd263c @jeremy tag_options creates fewer objects
jeremy authored
19
72f93b5 @jeremy Check whether blocks are called from erb using a special __in_erb_tem…
jeremy authored
20 # Returns an empty HTML tag of type +name+ which by default is XHTML
21 # compliant. Set +open+ to true to create an open tag compatible
22 # with HTML 4.0 and below. Add HTML attributes by passing an attributes
4b33306 @jeremy The tag helper may bypass escaping.
jeremy authored
23 # hash to +options+. Set +escape+ to false to disable attribute value
24 # escaping.
b00e6a9 @dhh Massive documentation update for all helpers (closes #8223, #8177, #8175
dhh authored
25 #
26 # ==== Options
95d8782 @fxn rewords a little the RDoc of the tag helper
fxn authored
27 # You can use symbols or strings for the attribute names.
28 #
cfcef34 @fxn Additional documentation for data-* attributes.
fxn authored
29 # Use +true+ with boolean attributes that can render with no value, like
30 # +disabled+ and +readonly+.
5e79094 @stephencelis HTML5 data attribute helpers [#5825 state:resolved].
stephencelis authored
31 #
cfcef34 @fxn Additional documentation for data-* attributes.
fxn authored
32 # HTML5 <tt>data-*</tt> attributes can be set with a single +data+ key
33 # pointing to a hash of sub-attributes.
5e79094 @stephencelis HTML5 data attribute helpers [#5825 state:resolved].
stephencelis authored
34 #
95d8782 @fxn rewords a little the RDoc of the tag helper
fxn authored
35 # To play nicely with JavaScript conventions sub-attributes are dasherized.
36 # For example, a key +user_id+ would render as <tt>data-user-id</tt> and
37 # thus accessed as <tt>dataset.userId</tt>.
cfcef34 @fxn Additional documentation for data-* attributes.
fxn authored
38 #
39 # Values are encoded to JSON, with the exception of strings and symbols.
40 # This may come in handy when using jQuery's HTML5-aware <tt>.data()<tt>
41 # from 1.4.3.
730c8e8 @technoweenie Clean up multiple calls to #stringify_keys in TagHelper, add better d…
technoweenie authored
42 #
b00e6a9 @dhh Massive documentation update for all helpers (closes #8223, #8177, #8175
dhh authored
43 # ==== Examples
730c8e8 @technoweenie Clean up multiple calls to #stringify_keys in TagHelper, add better d…
technoweenie authored
44 # tag("br")
b00e6a9 @dhh Massive documentation update for all helpers (closes #8223, #8177, #8175
dhh authored
45 # # => <br />
46 #
730c8e8 @technoweenie Clean up multiple calls to #stringify_keys in TagHelper, add better d…
technoweenie authored
47 # tag("br", nil, true)
b00e6a9 @dhh Massive documentation update for all helpers (closes #8223, #8177, #8175
dhh authored
48 # # => <br>
49 #
cfcef34 @fxn Additional documentation for data-* attributes.
fxn authored
50 # tag("input", :type => 'text', :disabled => true)
b00e6a9 @dhh Massive documentation update for all helpers (closes #8223, #8177, #8175
dhh authored
51 # # => <input type="text" disabled="disabled" />
52 #
cfcef34 @fxn Additional documentation for data-* attributes.
fxn authored
53 # tag("img", :src => "open & shut.png")
4b33306 @jeremy The tag helper may bypass escaping.
jeremy authored
54 # # => <img src="open &amp; shut.png" />
55 #
cfcef34 @fxn Additional documentation for data-* attributes.
fxn authored
56 # tag("img", {:src => "open &amp; shut.png"}, false, false)
4b33306 @jeremy The tag helper may bypass escaping.
jeremy authored
57 # # => <img src="open &amp; shut.png" />
5e79094 @stephencelis HTML5 data attribute helpers [#5825 state:resolved].
stephencelis authored
58 #
cfcef34 @fxn Additional documentation for data-* attributes.
fxn authored
59 # tag("div", :data => {:name => 'Stephen', :city_state => %w(Chicago IL)})
60 # # => <div data-name="Stephen" data-city-state="[&quot;Chicago&quot;,&quot;IL&quot;]" />
4b33306 @jeremy The tag helper may bypass escaping.
jeremy authored
61 def tag(name, options = nil, open = false, escape = true)
4cbb9db For performance reasons, you can no longer call html_safe! on Strings…
Yehuda Katz authored
62 "<#{name}#{tag_options(options, escape) if options}#{open ? ">" : " />"}".html_safe
db045db @dhh Initial
dhh authored
63 end
dfac1ce @dhh Fixed that form helpers would treat string and symbol keys differentl…
dhh authored
64
730c8e8 @technoweenie Clean up multiple calls to #stringify_keys in TagHelper, add better d…
technoweenie authored
65 # Returns an HTML block tag of type +name+ surrounding the +content+. Add
72f93b5 @jeremy Check whether blocks are called from erb using a special __in_erb_tem…
jeremy authored
66 # HTML attributes by passing an attributes hash to +options+.
b00e6a9 @dhh Massive documentation update for all helpers (closes #8223, #8177, #8175
dhh authored
67 # Instead of passing the content as an argument, you can also use a block
68 # in which case, you pass your +options+ as the second parameter.
4b33306 @jeremy The tag helper may bypass escaping.
jeremy authored
69 # Set escape to false to disable attribute value escaping.
730c8e8 @technoweenie Clean up multiple calls to #stringify_keys in TagHelper, add better d…
technoweenie authored
70 #
b00e6a9 @dhh Massive documentation update for all helpers (closes #8223, #8177, #8175
dhh authored
71 # ==== Options
72f93b5 @jeremy Check whether blocks are called from erb using a special __in_erb_tem…
jeremy authored
72 # The +options+ hash is used with attributes with no value like (<tt>disabled</tt> and
b00e6a9 @dhh Massive documentation update for all helpers (closes #8223, #8177, #8175
dhh authored
73 # <tt>readonly</tt>), which you can give a value of true in the +options+ hash. You can use
74 # symbols or strings for the attribute names.
75 #
76 # ==== Examples
730c8e8 @technoweenie Clean up multiple calls to #stringify_keys in TagHelper, add better d…
technoweenie authored
77 # content_tag(:p, "Hello world!")
78 # # => <p>Hello world!</p>
79 # content_tag(:div, content_tag(:p, "Hello world!"), :class => "strong")
80 # # => <div class="strong"><p>Hello world!</p></div>
81 # content_tag("select", options, :multiple => true)
82 # # => <select multiple="multiple">...options...</select>
6c06205 @dhh Added block-usage to TagHelper#content_tag [DHH]
dhh authored
83 #
04963f1 @jeroenvandijk Updated documentation for block helpers in tag_helper.rb
jeroenvandijk authored
84 # <%= content_tag :div, :class => "strong" do -%>
730c8e8 @technoweenie Clean up multiple calls to #stringify_keys in TagHelper, add better d…
technoweenie authored
85 # Hello world!
86 # <% end -%>
0432d15 @lifo Merge with docrails.
lifo authored
87 # # => <div class="strong">Hello world!</div>
4b33306 @jeremy The tag helper may bypass escaping.
jeremy authored
88 def content_tag(name, content_or_options_with_block = nil, options = nil, escape = true, &block)
6c06205 @dhh Added block-usage to TagHelper#content_tag [DHH]
dhh authored
89 if block_given?
90 options = content_or_options_with_block if content_or_options_with_block.is_a?(Hash)
4464b8e Deprecate block_called_from_erb? pending a solution for getting it in…
Carlhuda authored
91 content_tag_string(name, capture(&block), options, escape)
6c06205 @dhh Added block-usage to TagHelper#content_tag [DHH]
dhh authored
92 else
4d4c8e2 @jeremy Don't pass block binding to concat
jeremy authored
93 content_tag_string(name, content_or_options_with_block, options, escape)
6c06205 @dhh Added block-usage to TagHelper#content_tag [DHH]
dhh authored
94 end
db045db @dhh Initial
dhh authored
95 end
96
730c8e8 @technoweenie Clean up multiple calls to #stringify_keys in TagHelper, add better d…
technoweenie authored
97 # Returns a CDATA section with the given +content+. CDATA sections
f49dc37 @sstephenson Wrap javascript_tag contents in a CDATA section and add a cdata_secti…
sstephenson authored
98 # are used to escape blocks of text containing characters which would
99 # otherwise be recognized as markup. CDATA sections begin with the string
730c8e8 @technoweenie Clean up multiple calls to #stringify_keys in TagHelper, add better d…
technoweenie authored
100 # <tt><![CDATA[</tt> and end with (and may not contain) the string <tt>]]></tt>.
101 #
b00e6a9 @dhh Massive documentation update for all helpers (closes #8223, #8177, #8175
dhh authored
102 # ==== Examples
730c8e8 @technoweenie Clean up multiple calls to #stringify_keys in TagHelper, add better d…
technoweenie authored
103 # cdata_section("<hello world>")
b00e6a9 @dhh Massive documentation update for all helpers (closes #8223, #8177, #8175
dhh authored
104 # # => <![CDATA[<hello world>]]>
105 #
106 # cdata_section(File.read("hello_world.txt"))
107 # # => <![CDATA[<hello from a text file]]>
f49dc37 @sstephenson Wrap javascript_tag contents in a CDATA section and add a cdata_secti…
sstephenson authored
108 def cdata_section(content)
4cbb9db For performance reasons, you can no longer call html_safe! on Strings…
Yehuda Katz authored
109 "<![CDATA[#{content}]]>".html_safe
f49dc37 @sstephenson Wrap javascript_tag contents in a CDATA section and add a cdata_secti…
sstephenson authored
110 end
111
b00e6a9 @dhh Massive documentation update for all helpers (closes #8223, #8177, #8175
dhh authored
112 # Returns an escaped version of +html+ without affecting existing escaped entities.
dbd0bd5 @technoweenie Add <%= escape_once html %> to escape html while leaving any currentl…
technoweenie authored
113 #
b00e6a9 @dhh Massive documentation update for all helpers (closes #8223, #8177, #8175
dhh authored
114 # ==== Examples
dbbae5e @lifo Merge with docrails
lifo authored
115 # escape_once("1 < 2 &amp; 3")
b00e6a9 @dhh Massive documentation update for all helpers (closes #8223, #8177, #8175
dhh authored
116 # # => "1 &lt; 2 &amp; 3"
117 #
118 # escape_once("&lt;&lt; Accept & Checkout")
119 # # => "&lt;&lt; Accept &amp; Checkout"
dbd0bd5 @technoweenie Add <%= escape_once html %> to escape html while leaving any currentl…
technoweenie authored
120 def escape_once(html)
b16e0c9 @NZKoz Clean tag attributes before passing through the escape_once logic.
NZKoz authored
121 ActiveSupport::Multibyte.clean(html.to_s).gsub(/[\"><]|&(?!([a-zA-Z]+|(#\d+));)/) { |special| ERB::Util::HTML_ESCAPE[special] }
dbd0bd5 @technoweenie Add <%= escape_once html %> to escape html while leaving any currentl…
technoweenie authored
122 end
123
db045db @dhh Initial
dhh authored
124 private
72f93b5 @jeremy Check whether blocks are called from erb using a special __in_erb_tem…
jeremy authored
125
4b33306 @jeremy The tag helper may bypass escaping.
jeremy authored
126 def content_tag_string(name, content, options, escape = true)
127 tag_options = tag_options(options, escape) if options
399b493 @spastorino content_tag_string shouldn't escape_html if escape param is false
spastorino authored
128 "<#{name}#{tag_options}>#{escape ? ERB::Util.h(content) : content}</#{name}>".html_safe
6c06205 @dhh Added block-usage to TagHelper#content_tag [DHH]
dhh authored
129 end
064842f Convert boolean form options form the tag_helper. Recloses #809.
Marcel Molina authored
130
4b33306 @jeremy The tag helper may bypass escaping.
jeremy authored
131 def tag_options(options, escape = true)
8fd263c @jeremy tag_options creates fewer objects
jeremy authored
132 unless options.blank?
133 attrs = []
5786395 @rizwanreza Allow content_tag options to take an array [#1741 state:resolved] [ri…
rizwanreza authored
134 options.each_pair do |key, value|
5e79094 @stephencelis HTML5 data attribute helpers [#5825 state:resolved].
stephencelis authored
135 if key.to_s == 'data' && value.is_a?(Hash)
136 value.each do |k, v|
2f9e880 @NZKoz Rejig the html5 data helper code
NZKoz authored
137 if !v.is_a?(String) && !v.is_a?(Symbol)
138 v = v.to_json
139 end
330327e @spastorino Call html_escape in ERB::Util module and don't mix it in in the helpers
spastorino authored
140 v = ERB::Util.html_escape(v) if escape
2f9e880 @NZKoz Rejig the html5 data helper code
NZKoz authored
141 attrs << %(data-#{k.to_s.dasherize}="#{v}")
5e79094 @stephencelis HTML5 data attribute helpers [#5825 state:resolved].
stephencelis authored
142 end
143 elsif BOOLEAN_ATTRIBUTES.include?(key)
5786395 @rizwanreza Allow content_tag options to take an array [#1741 state:resolved] [ri…
rizwanreza authored
144 attrs << %(#{key}="#{key}") if value
145 elsif !value.nil?
146 final_value = value.is_a?(Array) ? value.join(" ") : value
330327e @spastorino Call html_escape in ERB::Util module and don't mix it in in the helpers
spastorino authored
147 final_value = ERB::Util.html_escape(final_value) if escape
5786395 @rizwanreza Allow content_tag options to take an array [#1741 state:resolved] [ri…
rizwanreza authored
148 attrs << %(#{key}="#{final_value}")
4b33306 @jeremy The tag helper may bypass escaping.
jeremy authored
149 end
8fd263c @jeremy tag_options creates fewer objects
jeremy authored
150 end
4cbb9db For performance reasons, you can no longer call html_safe! on Strings…
Yehuda Katz authored
151 " #{attrs.sort * ' '}".html_safe unless attrs.empty?
8fd263c @jeremy tag_options creates fewer objects
jeremy authored
152 end
064842f Convert boolean form options form the tag_helper. Recloses #809.
Marcel Molina authored
153 end
db045db @dhh Initial
dhh authored
154 end
155 end
7f26415 @dhh Optimized tag_options to not sort keys, which is no longer necessary …
dhh authored
156 end
Something went wrong with that request. Please try again.