From 0d6e8edc2a47a4b4c6824936632bfb83850db343 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Sat, 4 May 2013 15:09:22 +0200 Subject: Move actionpack/lib/action_view* into actionview/lib --- actionview/lib/action_view/helpers/tag_helper.rb | 176 +++++++++++++++++++++++ 1 file changed, 176 insertions(+) create mode 100644 actionview/lib/action_view/helpers/tag_helper.rb (limited to 'actionview/lib/action_view/helpers/tag_helper.rb') diff --git a/actionview/lib/action_view/helpers/tag_helper.rb b/actionview/lib/action_view/helpers/tag_helper.rb new file mode 100644 index 0000000000..732f35643a --- /dev/null +++ b/actionview/lib/action_view/helpers/tag_helper.rb @@ -0,0 +1,176 @@ +require 'active_support/core_ext/string/output_safety' +require 'set' + +module ActionView + # = Action View Tag Helpers + module Helpers #:nodoc: + # Provides methods to generate HTML tags programmatically when you can't use + # a Builder. By default, they output XHTML compliant tags. + module TagHelper + extend ActiveSupport::Concern + include CaptureHelper + + BOOLEAN_ATTRIBUTES = %w(disabled readonly multiple checked autobuffer + autoplay controls loop selected hidden scoped async + defer reversed ismap seamless muted required + autofocus novalidate formnovalidate open pubdate + itemscope allowfullscreen default inert sortable + truespeed typemustmatch).to_set + + BOOLEAN_ATTRIBUTES.merge(BOOLEAN_ATTRIBUTES.map {|attribute| attribute.to_sym }) + + PRE_CONTENT_STRINGS = { + :textarea => "\n" + } + + # Returns an empty HTML tag of type +name+ which by default is XHTML + # compliant. Set +open+ to true to create an open tag compatible + # with HTML 4.0 and below. Add HTML attributes by passing an attributes + # hash to +options+. Set +escape+ to false to disable attribute value + # escaping. + # + # ==== Options + # You can use symbols or strings for the attribute names. + # + # Use +true+ with boolean attributes that can render with no value, like + # +disabled+ and +readonly+. + # + # HTML5 data-* attributes can be set with a single +data+ key + # pointing to a hash of sub-attributes. + # + # To play nicely with JavaScript conventions sub-attributes are dasherized. + # For example, a key +user_id+ would render as data-user-id and + # thus accessed as dataset.userId. + # + # Values are encoded to JSON, with the exception of strings and symbols. + # This may come in handy when using jQuery's HTML5-aware .data() + # from 1.4.3. + # + # ==== Examples + # tag("br") + # # =>
+ # + # tag("br", nil, true) + # # =>
+ # + # tag("input", type: 'text', disabled: true) + # # => + # + # tag("img", src: "open & shut.png") + # # => + # + # tag("img", {src: "open & shut.png"}, false, false) + # # => + # + # tag("div", data: {name: 'Stephen', city_state: %w(Chicago IL)}) + # # =>
+ def tag(name, options = nil, open = false, escape = true) + "<#{name}#{tag_options(options, escape) if options}#{open ? ">" : " />"}".html_safe + end + + # Returns an HTML block tag of type +name+ surrounding the +content+. Add + # HTML attributes by passing an attributes hash to +options+. + # Instead of passing the content as an argument, you can also use a block + # in which case, you pass your +options+ as the second parameter. + # Set escape to false to disable attribute value escaping. + # + # ==== Options + # The +options+ hash is used with attributes with no value like (disabled and + # readonly), which you can give a value of true in the +options+ hash. You can use + # symbols or strings for the attribute names. + # + # ==== Examples + # content_tag(:p, "Hello world!") + # # =>

Hello world!

+ # content_tag(:div, content_tag(:p, "Hello world!"), class: "strong") + # # =>

Hello world!

+ # content_tag("select", options, multiple: true) + # # => + # + # <%= content_tag :div, class: "strong" do -%> + # Hello world! + # <% end -%> + # # =>
Hello world!
+ def content_tag(name, content_or_options_with_block = nil, options = nil, escape = true, &block) + if block_given? + options = content_or_options_with_block if content_or_options_with_block.is_a?(Hash) + content_tag_string(name, capture(&block), options, escape) + else + content_tag_string(name, content_or_options_with_block, options, escape) + end + end + + # Returns a CDATA section with the given +content+. CDATA sections + # are used to escape blocks of text containing characters which would + # otherwise be recognized as markup. CDATA sections begin with the string + # and end with (and may not contain) the string ]]>. + # + # cdata_section("") + # # => ]]> + # + # cdata_section(File.read("hello_world.txt")) + # # => + # + # cdata_section("hello]]>world") + # # => world]]> + def cdata_section(content) + splitted = content.gsub(']]>', ']]]]>') + "".html_safe + end + + # Returns an escaped version of +html+ without affecting existing escaped entities. + # + # escape_once("1 < 2 & 3") + # # => "1 < 2 & 3" + # + # escape_once("<< Accept & Checkout") + # # => "<< Accept & Checkout" + def escape_once(html) + ERB::Util.html_escape_once(html) + end + + private + + def content_tag_string(name, content, options, escape = true) + tag_options = tag_options(options, escape) if options + content = ERB::Util.h(content) if escape + "<#{name}#{tag_options}>#{PRE_CONTENT_STRINGS[name.to_sym]}#{content}".html_safe + end + + def tag_options(options, escape = true) + return if options.blank? + attrs = [] + options.each_pair do |key, value| + if key.to_s == 'data' && value.is_a?(Hash) + value.each_pair do |k, v| + attrs << data_tag_option(k, v, escape) + end + elsif BOOLEAN_ATTRIBUTES.include?(key) + attrs << boolean_tag_option(key) if value + elsif !value.nil? + attrs << tag_option(key, value, escape) + end + end + " #{attrs.sort! * ' '}".html_safe unless attrs.empty? + end + + def data_tag_option(key, value, escape) + key = "data-#{key.to_s.dasherize}" + unless value.is_a?(String) || value.is_a?(Symbol) || value.is_a?(BigDecimal) + value = value.to_json + end + tag_option(key, value, escape) + end + + def boolean_tag_option(key) + %(#{key}="#{key}") + end + + def tag_option(key, value, escape) + value = value.join(" ") if value.is_a?(Array) + value = ERB::Util.h(value) if escape + %(#{key}="#{value}") + end + end + end +end -- cgit v1.2.3