开发者

Rails 3 & HTML 5 Microdata

In Rails, is it possible to create a HTML 5 valueless attribute using any of the ActionView Helpers? I'm trying to create the HTML 5 itemprop microdata for google's BreadCrumbs. Here's the output I'd like to generate:

<div itemscope itemtype="http://data-vocabulary.org/Breadcrumb"></div>

But you can see that the itemscope attribute value has no value. Ideally, I'd like to开发者_运维百科 do something like this in Rails...

content_tag(:div, "somecontent", :itemscope => nil, :item_type => "http://data-vocabulary.org/Breadcrumb") 

... but I can't seem to get generate an attribute without a value.


No, you can't. Rails' tag helper defines a ActionView::Helpers::TagHelper::BOOLEAN_ATTRIBUTES array, and any attributes in that array will be outputted as key=key, so if you had, say, tag(:input, :type => :checkbox, :checked => true), the output should be <input type='checkbox' checked='checked' />.

I presume that this parses properly, since an XML parser is simply going to check for the presence of the attribute, so any value should work.

To that end, you could use:

content_tag(:div, "somecontent", :itemscope => "itemscope", :item_type ...

This will output itemscope="itemscope" in the tag, but it should result in the same desired effect when parsed.

Alternately, you could add itemscope to the BOOLEAN_ATTRIBUTES, then specify :itemscope => true.


You can achieve the result you want if you are willing to override a private Rails method. If you do this, you run the risk of causing problems when upgrading to future versions of Rails that update the private method logic. Since both <div itemscope ...> and <div itemscope="itemscope" ...> are valid according to the HTML5 spec, making the change below has very little payoff. The only reason I can think of to do this is if you are completely obsessive about your HTML code style.

As Chris Heald said, we will add itemscope to BOOLEAN_ATTRIBUTES and then override the tag helper to output boolean attributes without values. (The following tag_options method is modified from Rails/ActionPack 3.0.7 - future readers should copy the contemporary tag_options code and then make the change after the if BOOLEAN_ATTRIBUTES.include?(key) line.)

module ActionView
  module Helpers
    module TagHelper
      BOOLEAN_ATTRIBUTES.merge(['itemscope', :itemscope])
      private
      def tag_options(options, escape = true)
        unless options.blank?
          attrs = []
          options.each_pair do |key, value|
            if BOOLEAN_ATTRIBUTES.include?(key)
              attrs << key.to_s if value
            elsif !value.nil?
              final_value = value.is_a?(Array) ? value.join(" ") : value
              final_value = html_escape(final_value) if escape
              attrs << %(#{key}="#{final_value}")
            end
          end
          " #{attrs.sort * ' '}".html_safe unless attrs.empty?
        end
      end
    end
  end
end

You can now update your view with:

content_tag(:div, "somecontent", :itemscope => true, :item_type => "http://data-vocabulary.org/Breadcrumb"

FWIW, I store extensions to existing classes in e.g. lib/extensions/action_view.rb; these extensions are loaded by config/initializers/extensions.rb which consists of:

Dir[File.join(Rails.root, 'lib', 'extensions', '*.rb')].each {|f| require f}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜