aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack/lib/action_view
diff options
context:
space:
mode:
authorDavid Heinemeier Hansson <david@loudthinking.com>2007-06-23 17:49:18 +0000
committerDavid Heinemeier Hansson <david@loudthinking.com>2007-06-23 17:49:18 +0000
commitb00e6a984df51a2f891c2a4c819ac2ab08359eed (patch)
tree963bdbbc51159f294be459788c2a57eef0624f1d /actionpack/lib/action_view
parent8aefa3ee75e261488a39ea9d26a767c9db696c20 (diff)
downloadrails-b00e6a984df51a2f891c2a4c819ac2ab08359eed.tar.gz
rails-b00e6a984df51a2f891c2a4c819ac2ab08359eed.tar.bz2
rails-b00e6a984df51a2f891c2a4c819ac2ab08359eed.zip
Massive documentation update for all helpers (closes #8223, #8177, #8175, #8108, #7977, #7972, #7971, #7969) [jeremymcanally]
git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@7106 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
Diffstat (limited to 'actionpack/lib/action_view')
-rw-r--r--actionpack/lib/action_view/helpers/asset_tag_helper.rb108
-rw-r--r--actionpack/lib/action_view/helpers/benchmark_helper.rb17
-rw-r--r--actionpack/lib/action_view/helpers/cache_helper.rb29
-rw-r--r--actionpack/lib/action_view/helpers/capture_helper.rb118
-rwxr-xr-xactionpack/lib/action_view/helpers/date_helper.rb268
-rw-r--r--actionpack/lib/action_view/helpers/form_tag_helper.rb299
-rw-r--r--actionpack/lib/action_view/helpers/number_helper.rb111
-rw-r--r--actionpack/lib/action_view/helpers/tag_helper.rb50
-rw-r--r--actionpack/lib/action_view/helpers/text_helper.rb266
9 files changed, 1005 insertions, 261 deletions
diff --git a/actionpack/lib/action_view/helpers/asset_tag_helper.rb b/actionpack/lib/action_view/helpers/asset_tag_helper.rb
index 8b9e4094ce..6c4eb0931c 100644
--- a/actionpack/lib/action_view/helpers/asset_tag_helper.rb
+++ b/actionpack/lib/action_view/helpers/asset_tag_helper.rb
@@ -4,11 +4,15 @@ require 'action_view/helpers/tag_helper'
module ActionView
module Helpers #:nodoc:
- # Provides methods for linking an HTML page together with other assets such
- # as images, javascripts, stylesheets, and feeds. You can direct Rails to
- # link to assets from a dedicated assets server by setting ActionController::Base.asset_host
- # in your environment.rb. These methods do not verify the assets exist before
- # linking to them.
+ # This module provides methods for generating HTML that links views to assets such
+ # as images, javascripts, stylesheets, and feeds. These methods do not verify
+ # the assets exist before linking to them.
+ #
+ # === Using asset hosts
+ # By default, Rails links to these assets on the current host in the public
+ # folder, but you can direct Rails to link to assets from a dedicated assets server by
+ # setting ActionController::Base.asset_host in your environment.rb. For example,
+ # let's say your asset host is assets.example.com.
#
# ActionController::Base.asset_host = "assets.example.com"
# image_tag("rails.png")
@@ -16,15 +20,22 @@ module ActionView
# stylesheet_include_tag("application")
# => <link href="http://assets.example.com/stylesheets/application.css" media="screen" rel="Stylesheet" type="text/css" />
#
- # Since browsers typically open at most two connections to a single host,
- # your assets often wait in single file for their turn to load.
+ # This is useful since browsers typically open at most two connections to a single host,
+ # which means your assets often wait in single file for their turn to load. You can
+ # alleviate this by using a %d wildcard in <tt>asset_host</tt> (for example, "assets%d.example.com")
+ # to automatically distribute asset requests among four hosts (e.g., assets0.example.com through assets3.example.com)
+ # so browsers will open eight connections rather than two.
+ #
+ # image_tag("rails.png")
+ # => <img src="http://assets0.example.com/images/rails.png" alt="Rails" />
+ # stylesheet_include_tag("application")
+ # => <link href="http://assets3.example.com/stylesheets/application.css" media="screen" rel="Stylesheet" type="text/css" />
#
- # Use a %d wildcard in asset_host (asset%d.myapp.com) to automatically
- # distribute asset requests among four hosts (asset0-asset3.myapp.com)
- # so browsers will open eight connections rather than two. Use wildcard
- # DNS to CNAME the wildcard to your real asset host.
+ # To do this, you can either setup four actual hosts, or you can use wildcard DNS to CNAME
+ # the wildcard to a single asset host. You can read more about setting up your DNS CNAME records from
+ # your ISP.
#
- # Note: this is purely a browser performance optimization and is not meant
+ # Note: This is purely a browser performance optimization and is not meant
# for server load balancing. See http://www.die.net/musings/page_load_time/
# for background.
module AssetTagHelper
@@ -37,19 +48,24 @@ module ActionView
# <tt>:atom</tt>. Control the link options in url_for format using the
# +url_options+. You can modify the LINK tag itself in +tag_options+.
#
- # Tag Options:
+ # ==== Options:
# * <tt>:rel</tt> - Specify the relation of this link, defaults to "alternate"
# * <tt>:type</tt> - Override the auto-generated mime type
# * <tt>:title</tt> - Specify the title of the link, defaults to the +type+
#
+ # ==== Examples
# auto_discovery_link_tag # =>
- # <link rel="alternate" type="application/rss+xml" title="RSS" href="http://www.curenthost.com/controller/action" />
+ # <link rel="alternate" type="application/rss+xml" title="RSS" href="http://www.currenthost.com/controller/action" />
# auto_discovery_link_tag(:atom) # =>
- # <link rel="alternate" type="application/atom+xml" title="ATOM" href="http://www.curenthost.com/controller/action" />
+ # <link rel="alternate" type="application/atom+xml" title="ATOM" href="http://www.currenthost.com/controller/action" />
# auto_discovery_link_tag(:rss, {:action => "feed"}) # =>
- # <link rel="alternate" type="application/rss+xml" title="RSS" href="http://www.curenthost.com/controller/feed" />
+ # <link rel="alternate" type="application/rss+xml" title="RSS" href="http://www.currenthost.com/controller/feed" />
# auto_discovery_link_tag(:rss, {:action => "feed"}, {:title => "My RSS"}) # =>
- # <link rel="alternate" type="application/rss+xml" title="My RSS" href="http://www.curenthost.com/controller/feed" />
+ # <link rel="alternate" type="application/rss+xml" title="My RSS" href="http://www.currenthost.com/controller/feed" />
+ # auto_discovery_link_tag(:rss, {:controller => "news", :action => "feed"}) # =>
+ # <link rel="alternate" type="application/rss+xml" title="RSS" href="http://www.currenthost.com/news/feed" />
+ # auto_discovery_link_tag(:rss, "http://www.example.com/feed.rss", {:title => "Example RSS"}) # =>
+ # <link rel="alternate" type="application/rss+xml" title="Example RSS" href="http://www.example.com/feed" />
def auto_discovery_link_tag(type = :rss, url_options = {}, tag_options = {})
tag(
"link",
@@ -65,9 +81,12 @@ module ActionView
# Full paths from the document root will be passed through.
# Used internally by javascript_include_tag to build the script path.
#
+ # ==== Examples
# javascript_path "xmlhr" # => /javascripts/xmlhr.js
# javascript_path "dir/xmlhr.js" # => /javascripts/dir/xmlhr.js
# javascript_path "/dir/xmlhr" # => /dir/xmlhr.js
+ # javascript_path "http://www.railsapplication.com/js/xmlhr" # => http://www.railsapplication.com/js/xmlhr.js
+ # javascript_path "http://www.railsapplication.com/js/xmlhr.js" # => http://www.railsapplication.com/js/xmlhr.js
def javascript_path(source)
compute_public_path(source, 'javascripts', 'js')
end
@@ -85,22 +104,35 @@ module ActionView
# javascripts directory, it will be included as well. You can modify the
# html attributes of the script tag by passing a hash as the last argument.
#
+ # ==== Examples
# javascript_include_tag "xmlhr" # =>
# <script type="text/javascript" src="/javascripts/xmlhr.js"></script>
#
+ # javascript_include_tag "xmlhr.js" # =>
+ # <script type="text/javascript" src="/javascripts/xmlhr.js"></script>
+ #
# javascript_include_tag "common.javascript", "/elsewhere/cools" # =>
# <script type="text/javascript" src="/javascripts/common.javascript"></script>
# <script type="text/javascript" src="/elsewhere/cools.js"></script>
#
+ # javascript_include_tag "http://www.railsapplication.com/xmlhr" # =>
+ # <script type="text/javascript" src="http://www.railsapplication.com/xmlhr.js"></script>
+ #
+ # javascript_include_tag "http://www.railsapplication.com/xmlhr.js" # =>
+ # <script type="text/javascript" src="http://www.railsapplication.com/xmlhr.js"></script>
+ #
# javascript_include_tag :defaults # =>
# <script type="text/javascript" src="/javascripts/prototype.js"></script>
# <script type="text/javascript" src="/javascripts/effects.js"></script>
# ...
- # <script type="text/javascript" src="/javascripts/application.js"></script> *see below
+ # <script type="text/javascript" src="/javascripts/application.js"></script> <!-- * see below -->
#
# * = The application.js file is only referenced if it exists
#
- # You can also include all javascripts in the javascripts directory using :all as the source:
+ # Though it's not really recommended practice, if you need to extend the default JavaScript set for any reason
+ # (e.g., you're going to be using a certain .js file in every action), then take a look at the register_javascript_include_default method.
+ #
+ # You can also include all javascripts in the javascripts directory using <tt>:all</tt> as the source:
#
# javascript_include_tag :all # =>
# <script type="text/javascript" src="/javascripts/prototype.js"></script>
@@ -110,16 +142,17 @@ module ActionView
# <script type="text/javascript" src="/javascripts/shop.js"></script>
# <script type="text/javascript" src="/javascripts/checkout.js"></script>
#
- # Note that the default javascript files will be included first. So Prototype and Scriptaculous are available for
- # all subsequently included files. They
+ # Note that the default javascript files will be included first. So Prototype and Scriptaculous are available to
+ # all subsequently included files.
#
# == Caching multiple javascripts into one
#
- # You can also cache multiple javascripts into one file, which requires less HTTP connections and can better be
+ # You can also cache multiple javascripts into one file, which requires less HTTP connections to download and can better be
# compressed by gzip (leading to faster transfers). Caching will only happen if ActionController::Base.perform_caching
- # is set to true (which is the case by default for the Rails production environment, but not for the development
- # environment). Examples:
+ # is set to <tt>true</tt> (which is the case by default for the Rails production environment, but not for the development
+ # environment).
#
+ # ==== Examples
# javascript_include_tag :all, :cache => true # when ActionController::Base.perform_caching is false =>
# <script type="text/javascript" src="/javascripts/prototype.js"></script>
# <script type="text/javascript" src="/javascripts/effects.js"></script>
@@ -168,7 +201,7 @@ module ActionView
# Register one or more additional JavaScript files to be included when
# <tt>javascript_include_tag :defaults</tt> is called. This method is
- # only intended to be called from plugin initialization to register additional
+ # typically intended to be called from plugin initialization to register additional
# .js files that the plugin installed in <tt>public/javascripts</tt>.
def self.register_javascript_include_default(*sources)
@@javascript_default_sources.concat(sources)
@@ -183,9 +216,12 @@ module ActionView
# Full paths from the document root will be passed through.
# Used internally by stylesheet_link_tag to build the stylesheet path.
#
+ # ==== Examples
# stylesheet_path "style" # => /stylesheets/style.css
# stylesheet_path "dir/style.css" # => /stylesheets/dir/style.css
# stylesheet_path "/dir/style.css" # => /dir/style.css
+ # stylesheet_path "http://www.railsapplication.com/css/style" # => http://www.railsapplication.com/css/style.css
+ # stylesheet_path "http://www.railsapplication.com/css/style.js" # => http://www.railsapplication.com/css/style.css
def stylesheet_path(source)
compute_public_path(source, 'stylesheets', 'css')
end
@@ -194,12 +230,22 @@ module ActionView
# you don't specify an extension, .css will be appended automatically.
# You can modify the link attributes by passing a hash as the last argument.
#
+ # ==== Examples
# stylesheet_link_tag "style" # =>
# <link href="/stylesheets/style.css" media="screen" rel="Stylesheet" type="text/css" />
#
+ # stylesheet_link_tag "style.css" # =>
+ # <link href="/stylesheets/style.css" media="screen" rel="Stylesheet" type="text/css" />
+ #
+ # stylesheet_link_tag "http://www.railsapplication.com/style.css" # =>
+ # <link href="http://www.railsapplication.com/style.css" media="screen" rel="Stylesheet" type="text/css" />
+ #
# stylesheet_link_tag "style", :media => "all" # =>
# <link href="/stylesheets/style.css" media="all" rel="Stylesheet" type="text/css" />
#
+ # stylesheet_link_tag "style", :media => "print" # =>
+ # <link href="/stylesheets/style.css" media="print" rel="Stylesheet" type="text/css" />
+ #
# stylesheet_link_tag "random.styles", "/css/stylish" # =>
# <link href="/stylesheets/random.styles" media="screen" rel="Stylesheet" type="text/css" />
# <link href="/css/stylish.css" media="screen" rel="Stylesheet" type="text/css" />
@@ -218,6 +264,7 @@ module ActionView
# is set to true (which is the case by default for the Rails production environment, but not for the development
# environment). Examples:
#
+ # ==== Examples
# stylesheet_link_tag :all, :cache => true # when ActionController::Base.perform_caching is false =>
# <link href="/stylesheets/style1.css" media="screen" rel="Stylesheet" type="text/css" />
# <link href="/stylesheets/styleB.css" media="screen" rel="Stylesheet" type="text/css" />
@@ -271,9 +318,11 @@ module ActionView
# Used internally by image_tag to build the image path. Passing
# a filename without an extension is deprecated.
#
+ # ==== Examples
# image_path("edit.png") # => /images/edit.png
# image_path("icons/edit.png") # => /images/icons/edit.png
# image_path("/icons/edit.png") # => /icons/edit.png
+ # image_path("http://www.railsapplication.com/img/edit.png") # => http://www.railsapplication.com/img/edit.png
def image_path(source)
unless (source.split("/").last || source).include?(".") || source.blank?
ActiveSupport::Deprecation.warn(
@@ -289,7 +338,9 @@ module ActionView
# Returns an html image tag for the +source+. The +source+ can be a full
# path or a file that exists in your public images directory. Note that
# specifying a filename without the extension is now deprecated in Rails.
- # You can add html attributes using the +options+. The +options+ supports
+ #
+ # ==== Options
+ # You can add HTML attributes using the +options+. The +options+ supports
# two additional keys for convienence and conformance:
#
# * <tt>:alt</tt> - If no alt text is given, the file name part of the
@@ -298,12 +349,17 @@ module ActionView
# width="30" and height="45". <tt>:size</tt> will be ignored if the
# value is not in the correct format.
#
+ # ==== Examples
# image_tag("icon.png") # =>
# <img src="/images/icon.png" alt="Icon" />
# image_tag("icon.png", :size => "16x10", :alt => "Edit Entry") # =>
# <img src="/images/icon.png" width="16" height="10" alt="Edit Entry" />
# image_tag("/icons/icon.gif", :size => "16x16") # =>
# <img src="/icons/icon.gif" width="16" height="16" alt="Icon" />
+ # image_tag("/icons/icon.gif", :height => '32', :width => '32') # =>
+ # <img alt="Icon" height="32" src="/icons/icon.gif" width="32" />
+ # image_tag("/icons/icon.gif", :class => "menu_icon") # =>
+ # <img alt="Icon" class="menu_icon" src="/icons/icon.gif" />
def image_tag(source, options = {})
options.symbolize_keys!
diff --git a/actionpack/lib/action_view/helpers/benchmark_helper.rb b/actionpack/lib/action_view/helpers/benchmark_helper.rb
index 1d53be51db..fefa28f4d7 100644
--- a/actionpack/lib/action_view/helpers/benchmark_helper.rb
+++ b/actionpack/lib/action_view/helpers/benchmark_helper.rb
@@ -2,17 +2,24 @@ require 'benchmark'
module ActionView
module Helpers
+ # This helper offers a method to measure the execution time of a block
+ # in a template.
module BenchmarkHelper
- # Measures the execution time of a block in a template and reports the result to the log. Example:
+ # Allows you to measure the execution time of a block
+ # in a template and records the result to the log. Wrap this block around
+ # expensive operations or possible bottlenecks to get a time reading
+ # for the operation. For example, let's say you thought your file
+ # processing method was taking too long; you could wrap it in a benchmark block.
#
- # <% benchmark "Notes section" do %>
- # <%= expensive_notes_operation %>
+ # <% benchmark "Process data files" do %>
+ # <%= expensive_files_operation %>
# <% end %>
#
- # Will add something like "Notes section (0.34523)" to the log.
+ # That would add something like "Process data files (0.34523)" to the log,
+ # which you can then use to compare timings when optimizing your code.
#
# You may give an optional logger level as the second argument
- # (:debug, :info, :warn, :error). The default is :info.
+ # (:debug, :info, :warn, :error); the default value is :info.
def benchmark(message = "Benchmarking", level = :info)
if @logger
real = Benchmark.realtime { yield }
diff --git a/actionpack/lib/action_view/helpers/cache_helper.rb b/actionpack/lib/action_view/helpers/cache_helper.rb
index de2707ac75..cf5420a35e 100644
--- a/actionpack/lib/action_view/helpers/cache_helper.rb
+++ b/actionpack/lib/action_view/helpers/cache_helper.rb
@@ -1,7 +1,36 @@
module ActionView
module Helpers
+ # This helper to exposes a method for caching of view fragments.
# See ActionController::Caching::Fragments for usage instructions.
module CacheHelper
+ # A method for caching fragments of a view rather than an entire
+ # action or page. This technique is useful caching pieces like
+ # menus, lists of news topics, static HTML fragments, and so on.
+ # This method takes a block that contains the content you wish
+ # to cache. See ActionController::Caching::Fragments for more
+ # information.
+ #
+ # ==== Examples
+ # If you wanted to cache a navigation menu, you could do the
+ # following.
+ #
+ # <% cache do %>
+ # <%= render :partial => "menu" %>
+ # <% end %>
+ #
+ # You can also cache static content...
+ #
+ # <% cache do %>
+ # <p>Hello users! Welcome to our website!</p>
+ # <% end %>
+ #
+ # ...and static content mixed with RHTML content.
+ #
+ # <% cache do %>
+ # Topics:
+ # <%= render :partial => "topics", :collection => @topic_list %>
+ # <i>Topics listed alphabetically</i>
+ # <% end %>
def cache(name = {}, &block)
@controller.cache_erb_fragment(block, name)
end
diff --git a/actionpack/lib/action_view/helpers/capture_helper.rb b/actionpack/lib/action_view/helpers/capture_helper.rb
index 91cff4f981..7cf2b02659 100644
--- a/actionpack/lib/action_view/helpers/capture_helper.rb
+++ b/actionpack/lib/action_view/helpers/capture_helper.rb
@@ -1,58 +1,36 @@
module ActionView
module Helpers
- # Capture lets you extract parts of code which
- # can be used in other points of the template or even layout file.
- #
- # == Capturing a block into an instance variable
- #
- # <% @script = capture do %>
- # [some html...]
- # <% end %>
- #
- # == Add javascript to header using content_for
- #
- # content_for("name") is a wrapper for capture which will
- # make the fragment available by name to a yielding layout or template.
- #
- # layout.erb:
- #
- # <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
- # <head>
- # <title>layout with js</title>
- # <script type="text/javascript">
- # <%= yield :script %>
- # </script>
- # </head>
- # <body>
- # <%= yield %>
- # </body>
- # </html>
- #
- # view.erb
- #
- # This page shows an alert box!
- #
- # <% content_for("script") do %>
- # alert('hello world')
- # <% end %>
- #
- # Normal view text
+ # CaptureHelper exposes methods to let you extract generated markup which
+ # can be used in other parts of a template or layout file.
+ # It provides a method to capture blocks into variables through capture and
+ # a way to capture a block of code for use in a layout through content_for.
module CaptureHelper
- # Capture allows you to extract a part of the template into an
- # instance variable. You can use this instance variable anywhere
- # in your templates and even in your layout.
+ # The capture method allows you to extract a part of the template into a
+ # variable. You can then use this value anywhere in your templates or layout.
#
- # Example of capture being used in a .erb page:
+ # ==== Examples
+ # The capture method can be used in RHTML (ERb) templates...
#
# <% @greeting = capture do %>
- # Welcome To my shiny new web page!
+ # Welcome to my shiny new web page! The date and time is
+ # <%= Time.now %>
# <% end %>
#
- # Example of capture being used in a .builder page:
+ # ...and Builder (RXML) templates.
#
- # @greeting = capture do
- # 'Welcome To my shiny new web page!'
+ # @timestamp = capture do
+ # "The current timestamp is #{Time.now}."
# end
+ #
+ # You can then use the content as a variable anywhere else. For
+ # example:
+ #
+ # <html>
+ # <head><title><%= @greeting %></title></head>
+ # <body>
+ # <b><%= @greeting %></b>
+ # </body></html>
+ #
def capture(*args, &block)
# execute the block
begin
@@ -68,19 +46,53 @@ module ActionView
end
end
- # Calling content_for stores the block of markup for later use.
- # Subsequently, you can make calls to it by name with <tt>yield</tt>
- # in another template or in the layout.
+ # Calling content_for stores the block of markup in an identifier for later use.
+ # You can make subsequent calls to the stored content in another template or in the layout
+ # by calling it by name with <tt>yield</tt>.
#
- # Example:
+ # ==== Examples
#
- # <% content_for("header") do %>
- # alert('hello world')
+ # <% content_for("authorized") do %>
+ # alert('You are not authorized for that!')
+ # <% end %>
+ #
+ # You can then use <tt>yield :authorized</tt> anywhere in your templates.
+ #
+ # <%= yield :authorized if current_user == nil %>
+ #
+ # You can also use these variables in a layout. For example:
+ #
+ # <!-- This is the layout -->
+ # <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+ # <head>
+ # <title>My Website</title>
+ # <%= yield :script %>
+ # </head>
+ # <body>
+ # <%= yield %>
+ # </body>
+ # </html>
+ #
+ # And now we'll create a view that has a content_for call that
+ # creates the <tt>script</tt> identifier.
+ #
+ # <!-- This is our view -->
+ # Please login!
+ #
+ # <% content_for("script") do %>
+ # <script type="text/javascript">alert('You are not authorized for this action!')</script>
# <% end %>
#
- # You can use yield :header anywhere in your templates.
+ # Then in another view you may want to do something like this:
+ #
+ # <%= link_to_remote 'Logout', :action => 'logout' %>
+ #
+ # <% content_for("script") do %>
+ # <%= javascript_include_tag :defaults %>
+ # <% end %>
#
- # <%= yield :header %>
+ # That will include Prototype and Scriptaculous into the page; this technique
+ # is useful if you'll only be using these scripts on a few views.
#
# NOTE: Beware that content_for is ignored in caches. So you shouldn't use it
# for elements that are going to be fragment cached.
diff --git a/actionpack/lib/action_view/helpers/date_helper.rb b/actionpack/lib/action_view/helpers/date_helper.rb
index 6ab2596439..9903bed34d 100755
--- a/actionpack/lib/action_view/helpers/date_helper.rb
+++ b/actionpack/lib/action_view/helpers/date_helper.rb
@@ -37,12 +37,24 @@ module ActionView
# 40-59 secs # => less than a minute
# 60-89 secs # => 1 minute
#
- # Examples:
- #
+ # ==== Examples
# from_time = Time.now
- # distance_of_time_in_words(from_time, from_time + 50.minutes) # => about 1 hour
- # distance_of_time_in_words(from_time, from_time + 15.seconds) # => less than a minute
- # distance_of_time_in_words(from_time, from_time + 15.seconds, true) # => less than 20 seconds
+ # distance_of_time_in_words(from_time, from_time + 50.minutes) # => about 1 hour
+ # distance_of_time_in_words(from_time, 50.minutes.from_now) # => about 1 hour
+ # distance_of_time_in_words(from_time, from_time + 15.seconds) # => less than a minute
+ # distance_of_time_in_words(from_time, from_time + 15.seconds, true) # => less than 20 seconds
+ # distance_of_time_in_words(from_time, 3.years.from_now) # => over 3 years
+ # distance_of_time_in_words(from_time, from_time + 60.hours) # => about 3 days
+ # distance_of_time_in_words(from_time, from_time + 45.seconds, true) # => less than a minute
+ # distance_of_time_in_words(from_time, from_time - 45.seconds, true) # => less than a minute
+ # distance_of_time_in_words(from_time, 76.seconds.from_now) # => 1 minute
+ # distance_of_time_in_words(from_time, from_time + 1.year + 3.days) # => about 1 years
+ # distance_of_time_in_words(from_time, from_time + 4.years + 15.days + 30.minutes + 5.seconds) # => over 4 years
+ #
+ # to_time = Time.now + 6.years + 19.days
+ # distance_of_time_in_words(from_time, to_time, true) # => over 6 years
+ # distance_of_time_in_words(to_time, from_time, true) # => over 6 years
+ # distance_of_time_in_words(Time.now, Time.now) # => less than a minute
#
# Note: Rails calculates one year as 365.25 days.
def distance_of_time_in_words(from_time, to_time = 0, include_seconds = false)
@@ -76,6 +88,13 @@ module ActionView
end
# Like distance_of_time_in_words, but where <tt>to_time</tt> is fixed to <tt>Time.now</tt>.
+ #
+ # ==== Examples
+ # time_ago_in_words(3.minutes.from_now) # => 3 minutes
+ # time_ago_in_words(Time.now - 15.hours) # => 15 hours
+ # time_ago_in_words(Time.now) # => less than a minute
+ #
+ # from_time = Time.now - 3.days - 14.minutes - 25.seconds # => 3 days
def time_ago_in_words(from_time, include_seconds = false)
distance_of_time_in_words(from_time, Time.now, include_seconds)
end
@@ -96,16 +115,34 @@ module ActionView
#
# NOTE: Discarded selects will default to 1. So if no month select is available, January will be assumed.
#
- # Examples:
- #
+ # ==== Examples
+ # # Generates a date select that when POSTed is stored in the post variable, in the written_on attribute
# date_select("post", "written_on")
+ #
+ # # Generates a date select that when POSTed is stored in the post variable, in the written_on attribute,
+ # # with the year in the year drop down box starting at 1995.
# date_select("post", "written_on", :start_year => 1995)
+ #
+ # # Generates a date select that when POSTed is stored in the post variable, in the written_on attribute,
+ # # with the year in the year drop down box starting at 1995, numbers used for months instead of words,
+ # # and without a day select box.
# date_select("post", "written_on", :start_year => 1995, :use_month_numbers => true,
# :discard_day => true, :include_blank => true)
+ #
+ # # Generates a date select that when POSTed is stored in the post variable, in the written_on attribute
+ # # with the fields ordered as day, month, year rather than month, day, year.
# date_select("post", "written_on", :order => [:day, :month, :year])
- # date_select("user", "birthday", :order => [:month, :day])
#
+ # # Generates a date select that when POSTed is stored in the user variable, in the birthday attribute
+ # # lacking a year field.
+ # date_select("user", "birthday", :order => [:month, :day])
+ #
+ # # Generates a date select that when POSTed is stored in the user variable, in the birthday attribute
+ # # which is initially set to the date 3 days from the current date
# date_select("post", "written_on", :default => 3.days.from_now)
+ #
+ # # Generates a date select that when POSTed is stored in the credit_card variable, in the bill_due attribute
+ # # that will have a default day of 20.
# date_select("credit_card", "bill_due", :default => { :day => 20 })
#
# The selects are prepared for multi-parameter assignment to an Active Record object.
@@ -119,11 +156,25 @@ module ActionView
# Returns a set of select tags (one for hour, minute and optionally second) pre-selected for accessing a specified
# time-based attribute (identified by +method+) on an object assigned to the template (identified by +object+).
# You can include the seconds with <tt>:include_seconds</tt>.
- # Examples:
- #
+ #
+ # ==== Examples
+ # # Creates a time select tag that, when POSTed, will be stored in the post variable in the sunrise attribute
# time_select("post", "sunrise")
+ #
+ # # Creates a time select tag that, when POSTed, will be stored in the order variable in the submitted attribute
+ # time_select("order", "submitted")
+ #
+ # # Creates a time select tag that, when POSTed, will be stored in the mail variable in the sent_at attribute
+ # time_select("mail", "sent_at")
+ #
+ # # Creates a time select tag with a seconds field that, when POSTed, will be stored in the post variables in
+ # # the sunrise attribute.
# time_select("post", "start_time", :include_seconds => true)
#
+ # # Creates a time select tag with a seconds field that, when POSTed, will be stored in the entry variables in
+ # # the submission_time attribute.
+ # time_select("entry", "submission_time", :include_seconds => true)
+ #
# The selects are prepared for multi-parameter assignment to an Active Record object.
#
# Note: If the day is not included as an option but the month is, the day will be set to the 1st to ensure that all month
@@ -135,9 +186,22 @@ module ActionView
# Returns a set of select tags (one for year, month, day, hour, and minute) pre-selected for accessing a specified datetime-based
# attribute (identified by +method+) on an object assigned to the template (identified by +object+). Examples:
#
+ # ==== Examples
+ # # Generates a datetime select that, when POSTed, will be stored in the post variable in the written_on attribute
# datetime_select("post", "written_on")
+ #
+ # # Generates a datetime select with a year select that starts at 1995 that, when POSTed, will be stored in the
+ # # post variable in the written_on attribute.
# datetime_select("post", "written_on", :start_year => 1995)
#
+ # # Generates a datetime select with a default value of 3 days from the current time that, when POSTed, will be stored in the
+ # # trip variable in the departing attribute.
+ # datetime_select("trip", "departing", :default => 3.days.from_now)
+ #
+ # # Generates a datetime select that discards the type that, when POSTed, will be stored in the post variable as the written_on
+ # # attribute.
+ # datetime_select("post", "written_on", :discard_type => true)
+ #
# The selects are prepared for multi-parameter assignment to an Active Record object.
def datetime_select(object_name, method, options = {})
InstanceTag.new(object_name, method, self, nil, options.delete(:object)).to_datetime_select_tag(options)
@@ -148,7 +212,33 @@ module ActionView
# symbols <tt>:year</tt>, <tt>:month</tt> and <tt>:day</tt> in the desired order. If you do not supply a Symbol, it
# will be appened onto the <tt>:order</tt> passed in. You can also add <tt>:date_separator</tt> and <tt>:time_separator</tt>
# keys to the +options+ to control visual display of the elements.
- def select_datetime(datetime = Time.now, options = {})
+ #
+ # ==== Examples
+ # my_date_time = Time.now + 4.days
+ #
+ # # Generates a datetime select that defaults to the datetime in my_date_time (four days after today)
+ # select_datetime(my_date_time)
+ #
+ # # Generates a datetime select that defaults to today (no specified datetime)
+ # select_datetime()
+ #
+ # # Generates a datetime select that defaults to the datetime in my_date_time (four days after today)
+ # # with the fields ordered year, month, day rather then month, day, year.
+ # select_datetime(my_date_time, :order => [:year, :month, :day])
+ #
+ # # Generates a datetime select that defaults to the datetime in my_date_time (four days after today)
+ # # with a '/' between each date field.
+ # select_datetime(my_date_time, :date_separator => '/')
+ #
+ # # Generates a datetime select that discards the type of the field and defaults to the datetime in
+ # # my_date_time (four days after today)
+ # select_datetime(my_date_time, :discard_type => true)
+ #
+ # # Generates a datetime select that defaults to the datetime in my_date_time (four days after today)
+ # # prefixed with 'payday' rather than 'date'
+ # select_datetime(my_date_time, :prefix => 'payday')
+ #
+ def select_datetime(datetime = Time.now, options = {})
separator = options[:datetime_separator] || ''
select_date(datetime, options) + separator + select_time(datetime, options)
end
@@ -157,6 +247,28 @@ module ActionView
# It's possible to explicitly set the order of the tags using the <tt>:order</tt> option with an array of
# symbols <tt>:year</tt>, <tt>:month</tt> and <tt>:day</tt> in the desired order. If you do not supply a Symbol, it
# will be appened onto the <tt>:order</tt> passed in.
+ #
+ # ==== Examples
+ # my_date = Time.today + 6.days
+ #
+ # # Generates a date select that defaults to the date in my_date (six days after today)
+ # select_date(my_date)
+ #
+ # # Generates a date select that defaults to today (no specified date)
+ # select_date()
+ #
+ # # Generates a date select that defaults to the date in my_date (six days after today)
+ # # with the fields ordered year, month, day rather then month, day, year.
+ # select_date(my_date, :order => [:year, :month, :day])
+ #
+ # # Generates a date select that discards the type of the field and defaults to the date in
+ # # my_date (six days after today)
+ # select_datetime(my_date_time, :discard_type => true)
+ #
+ # # Generates a date select that defaults to the datetime in my_date (six days after today)
+ # # prefixed with 'payday' rather than 'date'
+ # select_datetime(my_date_time, :prefix => 'payday')
+ #
def select_date(date = Date.today, options = {})
options[:order] ||= []
[:year, :month, :day].each { |o| options[:order].push(o) unless options[:order].include?(o) }
@@ -169,7 +281,30 @@ module ActionView
end
# Returns a set of html select-tags (one for hour and minute)
- # You can set <tt>:add_separator</tt> key to format the output.
+ # You can set <tt>:time_separator</tt> key to format the output, and
+ # the <tt>:include_seconds</tt> option to include an input for seconds.
+ #
+ # ==== Examples
+ # my_time = Time.now + 5.days + 7.hours + 3.minutes + 14.seconds
+ #
+ # # Generates a time select that defaults to the time in my_time
+ # select_time(my_time)
+ #
+ # # Generates a time select that defaults to the current time (no specified time)
+ # select_time()
+ #
+ # # Generates a time select that defaults to the time in my_time,
+ # # which has fields separated by ':'
+ # select_time(my_time, :time_separator => ':')
+ #
+ # # Generates a time select that defaults to the time in my_time,
+ # # that also includes an input for seconds
+ # select_time(my_time, :include_seconds => true)
+ #
+ # # Generates a time select that defaults to the time in my_time, that has fields
+ # # separated by ':' and includes an input for seconds
+ # select_time(my_time, :time_separator => ':', :include_seconds => true)
+ #
def select_time(datetime = Time.now, options = {})
separator = options[:time_separator] || ''
select_hour(datetime, options) + separator + select_minute(datetime, options) + (options[:include_seconds] ? separator + select_second(datetime, options) : '')
@@ -178,6 +313,20 @@ module ActionView
# Returns a select tag with options for each of the seconds 0 through 59 with the current second selected.
# The <tt>second</tt> can also be substituted for a second number.
# Override the field name using the <tt>:field_name</tt> option, 'second' by default.
+ #
+ # ==== Examples
+ # my_time = Time.now + 16.minutes
+ #
+ # # Generates a select field for seconds that defaults to the seconds for the time in my_time
+ # select_second(my_time)
+ #
+ # # Generates a select field for seconds that defaults to the number given
+ # select_second(33)
+ #
+ # # Generates a select field for seconds that defaults to the seconds for the time in my_time
+ # # that is named 'interval' rather than 'second'
+ # select_second(my_time, :field_name => 'interval')
+ #
def select_second(datetime, options = {})
val = datetime ? (datetime.kind_of?(Fixnum) ? datetime : datetime.sec) : ''
if options[:use_hidden]
@@ -198,6 +347,20 @@ module ActionView
# Also can return a select tag with options by <tt>minute_step</tt> from 0 through 59 with the 00 minute selected
# The <tt>minute</tt> can also be substituted for a minute number.
# Override the field name using the <tt>:field_name</tt> option, 'minute' by default.
+ #
+ # ==== Examples
+ # my_time = Time.now + 6.hours
+ #
+ # # Generates a select field for minutes that defaults to the minutes for the time in my_time
+ # select_minute(my_time)
+ #
+ # # Generates a select field for minutes that defaults to the number given
+ # select_minute(14)
+ #
+ # # Generates a select field for minutes that defaults to the minutes for the time in my_time
+ # # that is named 'stride' rather than 'second'
+ # select_minute(my_time, :field_name => 'stride')
+ #
def select_minute(datetime, options = {})
val = datetime ? (datetime.kind_of?(Fixnum) ? datetime : datetime.min) : ''
if options[:use_hidden]
@@ -217,6 +380,20 @@ module ActionView
# Returns a select tag with options for each of the hours 0 through 23 with the current hour selected.
# The <tt>hour</tt> can also be substituted for a hour number.
# Override the field name using the <tt>:field_name</tt> option, 'hour' by default.
+ #
+ # ==== Examples
+ # my_time = Time.now + 6.hours
+ #
+ # # Generates a select field for minutes that defaults to the minutes for the time in my_time
+ # select_minute(my_time)
+ #
+ # # Generates a select field for minutes that defaults to the number given
+ # select_minute(14)
+ #
+ # # Generates a select field for minutes that defaults to the minutes for the time in my_time
+ # # that is named 'stride' rather than 'second'
+ # select_minute(my_time, :field_name => 'stride')
+ #
def select_hour(datetime, options = {})
val = datetime ? (datetime.kind_of?(Fixnum) ? datetime : datetime.hour) : ''
if options[:use_hidden]
@@ -236,6 +413,20 @@ module ActionView
# Returns a select tag with options for each of the days 1 through 31 with the current day selected.
# The <tt>date</tt> can also be substituted for a hour number.
# Override the field name using the <tt>:field_name</tt> option, 'day' by default.
+ #
+ # ==== Examples
+ # my_date = Time.today + 2.days
+ #
+ # # Generates a select field for days that defaults to the day for the date in my_date
+ # select_day(my_time)
+ #
+ # # Generates a select field for days that defaults to the number given
+ # select_day(5)
+ #
+ # # Generates a select field for days that defaults to the day for the date in my_date
+ # # that is named 'due' rather than 'day'
+ # select_day(my_time, :field_name => 'due')
+ #
def select_day(date, options = {})
val = date ? (date.kind_of?(Fixnum) ? date : date.day) : ''
if options[:use_hidden]
@@ -258,17 +449,34 @@ module ActionView
# set the <tt>:use_month_numbers</tt> key in +options+ to true for this to happen. If you want both numbers and names,
# set the <tt>:add_month_numbers</tt> key in +options+ to true. If you would prefer to show month names as abbreviations,
# set the <tt>:use_short_month</tt> key in +options+ to true. If you want to use your own month names, set the
- # <tt>:use_month_names</tt> key in +options+ to an array of 12 month names.
+ # <tt>:use_month_names</tt> key in +options+ to an array of 12 month names. Override the field name using the
+ # <tt>:field_name</tt> option, 'month' by default.
#
- # Examples:
+ # ==== Examples
+ # # Generates a select field for months that defaults to the current month that
+ # # will use keys like "January", "March".
+ # select_month(Date.today)
#
- # select_month(Date.today) # Will use keys like "January", "March"
- # select_month(Date.today, :use_month_numbers => true) # Will use keys like "1", "3"
- # select_month(Date.today, :add_month_numbers => true) # Will use keys like "1 - January", "3 - March"
- # select_month(Date.today, :use_short_month => true) # Will use keys like "Jan", "Mar"
- # select_month(Date.today, :use_month_names => %w(Januar Februar Marts ...)) # Will use keys like "Januar", "Marts"
+ # # Generates a select field for months that defaults to the current month that
+ # # is named "start" rather than "month"
+ # select_month(Date.today, :field_name => 'start')
+ #
+ # # Generates a select field for months that defaults to the current month that
+ # # will use keys like "1", "3".
+ # select_month(Date.today, :use_month_numbers => true)
+ #
+ # # Generates a select field for months that defaults to the current month that
+ # # will use keys like "1 - January", "3 - March".
+ # select_month(Date.today, :add_month_numbers => true)
+ #
+ # # Generates a select field for months that defaults to the current month that
+ # # will use keys like "Jan", "Mar".
+ # select_month(Date.today, :use_short_month => true)
+ #
+ # # Generates a select field for months that defaults to the current month that
+ # # will use keys like "Januar", "Marts."
+ # select_month(Date.today, :use_month_names => %w(Januar Februar Marts ...))
#
- # Override the field name using the <tt>:field_name</tt> option, 'month' by default.
def select_month(date, options = {})
val = date ? (date.kind_of?(Fixnum) ? date : date.month) : ''
if options[:use_hidden]
@@ -298,13 +506,25 @@ module ActionView
# Returns a select tag with options for each of the five years on each side of the current, which is selected. The five year radius
# can be changed using the <tt>:start_year</tt> and <tt>:end_year</tt> keys in the +options+. Both ascending and descending year
# lists are supported by making <tt>:start_year</tt> less than or greater than <tt>:end_year</tt>. The <tt>date</tt> can also be
- # substituted for a year given as a number. Example:
+ # substituted for a year given as a number. Override the field name using the <tt>:field_name</tt> option, 'year' by default.
+ #
+ # ==== Examples
+ # # Generates a select field for years that defaults to the current year that
+ # # has ascending year values
+ # select_year(Date.today, :start_year => 1992, :end_year => 2007)
+ #
+ # # Generates a select field for years that defaults to the current year that
+ # # is named 'birth' rather than 'year'
+ # select_year(Date.today, :field_name => 'birth')
+ #
+ # # Generates a select field for years that defaults to the current year that
+ # # has descending year values
+ # select_year(Date.today, :start_year => 2005, :end_year => 1900)
#
- # select_year(Date.today, :start_year => 1992, :end_year => 2007) # ascending year values
- # select_year(Date.today, :start_year => 2005, :end_year => 1900) # descending year values
+ # # Generates a select field for years that defaults to the year 2006 that
+ # # has ascending year values
# select_year(2006, :start_year => 2000, :end_year => 2010)
#
- # Override the field name using the <tt>:field_name</tt> option, 'year' by default.
def select_year(date, options = {})
val = date ? (date.kind_of?(Fixnum) ? date : date.year) : ''
if options[:use_hidden]
diff --git a/actionpack/lib/action_view/helpers/form_tag_helper.rb b/actionpack/lib/action_view/helpers/form_tag_helper.rb
index cf8fb74f59..bf82fa234a 100644
--- a/actionpack/lib/action_view/helpers/form_tag_helper.rb
+++ b/actionpack/lib/action_view/helpers/form_tag_helper.rb
@@ -3,33 +3,36 @@ require 'action_view/helpers/tag_helper'
module ActionView
module Helpers
- # Provides a number of methods for creating form tags that doesn't rely on conventions with an object assigned to the template like
- # FormHelper does. With the FormTagHelper, you provide the names and values yourself.
+ # Provides a number of methods for creating form tags that doesn't rely on an ActiveRecord object assigned to the template like
+ # FormHelper does. Instead, you provide the names and values manually.
#
- # NOTE: The html options disabled, readonly, and multiple can all be treated as booleans. So specifying <tt>:disabled => true</tt>
- # will give <tt>disabled="disabled"</tt>.
+ # NOTE: The HTML options <tt>disabled</tt>, <tt>readonly</tt>, and <tt>multiple</tt> can all be treated as booleans. So specifying
+ # <tt>:disabled => true</tt> will give <tt>disabled="disabled"</tt>.
module FormTagHelper
# Starts a form tag that points the action to an url configured with <tt>url_for_options</tt> just like
# ActionController::Base#url_for. The method for the form defaults to POST.
#
- # Examples:
- # * <tt>form_tag('/posts') => <form action="/posts" method="post"></tt>
- # * <tt>form_tag('/posts/1', :method => :put) => <form action="/posts/1" method="put"></tt>
- # * <tt>form_tag('/upload', :multipart => true) => <form action="/upload" method="post" enctype="multipart/form-data"></tt>
- #
- # ERb example:
- # <% form_tag '/posts' do -%>
- # <div><%= submit_tag 'Save' %></div>
- # <% end -%>
- #
- # Will output:
- # <form action="/posts" method="post"><div><input type="submit" name="submit" value="Save" /></div></form>
- #
- # Options:
+ # ==== Options
# * <tt>:multipart</tt> - If set to true, the enctype is set to "multipart/form-data".
# * <tt>:method</tt> - The method to use when submitting the form, usually either "get" or "post".
# If "put", "delete", or another verb is used, a hidden input with name _method
# is added to simulate the verb over post.
+ # * A list of parameters to feed to the URL the form will be posted to.
+ #
+ # ==== Examples
+ # form_tag('/posts')
+ # # => <form action="/posts" method="post">
+ #
+ # form_tag('/posts/1', :method => :put)
+ # # => <form action="/posts/1" method="put">
+ #
+ # form_tag('/upload', :multipart => true)
+ # # => <form action="/upload" method="post" enctype="multipart/form-data">
+ #
+ # <% form_tag '/posts' do -%>
+ # <div><%= submit_tag 'Save' %></div>
+ # <% end -%>
+ # # => <form action="/posts" method="post"><div><input type="submit" name="submit" value="Save" /></div></form>
def form_tag(url_for_options = {}, options = {}, *parameters_for_url, &block)
html_options = html_options_for_form(url_for_options, options, *parameters_for_url)
if block_given?
@@ -39,45 +42,101 @@ module ActionView
end
end
-
# Creates a dropdown selection box, or if the <tt>:multiple</tt> option is set to true, a multiple
# choice selection box.
#
# Helpers::FormOptions can be used to create common select boxes such as countries, time zones, or
- # associated records.
+ # associated records. <tt>option_tags</tt> is a string containing the option tags for the select box.
+ #
+ # ==== Options
+ # * <tt>:multiple</tt> - If set to true the selection will allow multiple choices.
+ # * <tt>:disabled</tt> - If set to true, the user will not be able to use this input.
+ # * Any other key creates standard HTML attributes for the tag.
#
- # <tt>option_tags</tt> is a string containing the option tags for the select box:
- # # Outputs <select id="people" name="people"><option>David</option></select>
+ # ==== Examples
# select_tag "people", "<option>David</option>"
+ # # => <select id="people" name="people"><option>David</option></select>
#
- # Options:
- # * <tt>:multiple</tt> - If set to true the selection will allow multiple choices.
+ # select_tag "count", "<option>1</option><option>2</option><option>3</option><option>4</option>"
+ # # => <select id="count" name="count"><option>1</option><option>2</option>
+ # # <option>3</option><option>4</option></select>
+ #
+ # select_tag "colors", "<option>Red</option><option>Green</option><option>Blue</option>", :multiple => true
+ # # => <select id="colors" multiple="multiple" name="colors"><option>Red</option>
+ # # <option>Green</option><option>Blue</option></select>
+ #
+ # select_tag "locations", "<option>Home</option><option selected="selected">Work</option><option>Out</option>"
+ # # => <select id="locations" name="locations"><option>Home</option><option selected='selected'>Work</option>
+ # # <option>Out</option></select>
+ #
+ # select_tag "access", "<option>Read</option><option>Write</option>", :multiple => true, :class => 'form_input'
+ # # => <select class="form_input" id="access" multiple="multiple" name="access"><option>Read</option>
+ # # <option>Write</option></select>
+ #
+ # select_tag "destination", "<option>NYC</option><option>Paris</option><option>Rome</option>", :disabled => true
+ # # => <select disabled="disabled" id="destination" name="destination"><option>NYC</option>
+ # # <option>Paris</option><option>Rome</option></select>
def select_tag(name, option_tags = nil, options = {})
content_tag :select, option_tags, { "name" => name, "id" => name }.update(options.stringify_keys)
end
- # Creates a standard text field.
+ # Creates a standard text field; use these text fields to input smaller chunks of text like a username
+ # or a search query.
#
- # Options:
+ # ==== Options
# * <tt>:disabled</tt> - If set to true, the user will not be able to use this input.
# * <tt>:size</tt> - The number of visible characters that will fit in the input.
# * <tt>:maxlength</tt> - The maximum number of characters that the browser will allow the user to enter.
+ # * Any other key creates standard HTML attributes for the tag.
#
- # A hash of standard HTML options for the tag.
+ # ==== Examples
+ # text_field_tag 'name'
+ # # => <input id="name" name="name" type="text" />
+ #
+ # text_field_tag 'query', 'Enter your search query here'
+ # # => <input id="query" name="query" type="text" value="Enter your search query here" />
+ #
+ # text_field_tag 'request', nil, :class => 'special_input'
+ # # => <input class="special_input" id="request" name="request" type="text" />
+ #
+ # text_field_tag 'address', '', :size => 75
+ # # => <input id="address" name="address" size="75" type="text" value="" />
+ #
+ # text_field_tag 'zip', nil, :maxlength => 5
+ # # => <input id="zip" maxlength="5" name="zip" type="text" />
+ #
+ # text_field_tag 'payment_amount', '$0.00', :disabled => true
+ # # => <input disabled="disabled" id="payment_amount" name="payment_amount" type="text" value="$0.00" />
+ #
+ # text_field_tag 'ip', '0.0.0.0', :maxlength => 15, :size => 20, :class => "ip-input"
+ # # => <input class="ip-input" id="ip" maxlength="15" name="ip" size="20" type="text" value="0.0.0.0" />
def text_field_tag(name, value = nil, options = {})
tag :input, { "type" => "text", "name" => name, "id" => name, "value" => value }.update(options.stringify_keys)
end
- # Creates a hidden field.
+ # Creates a hidden form input field used to transmit data that would be lost due to HTTP's statelessness or
+ # data that should be hidden from the user.
+ #
+ # ==== Options
+ # * Creates standard HTML attributes for the tag.
+ #
+ # ==== Examples
+ # hidden_field_tag 'tags_list'
+ # # => <input id="tags_list" name="tags_list" type="hidden" />
#
- # Takes the same options as text_field_tag
+ # hidden_field_tag 'token', 'VUBJKB23UIVI1UU1VOBVI@'
+ # # => <input id="token" name="token" type="hidden" value="VUBJKB23UIVI1UU1VOBVI@" />
+ #
+ # hidden_field_tag 'collected_input', '', :onchange => "alert('Input collected!')"
+ # # => <input id="collected_input" name="collected_input" onchange="alert('Input collected!')"
+ # # type="hidden" value="" />
def hidden_field_tag(name, value = nil, options = {})
text_field_tag(name, value, options.stringify_keys.update("type" => "hidden"))
end
- # Creates a file upload field.
+ # Creates a file upload field. If you are using file uploads then you will also need
+ # to set the multipart option for the form tag:
#
- # If you are using file uploads then you will also need to set the multipart option for the form:
# <%= form_tag { :action => "post" }, { :multipart => true } %>
# <label for="file">File to Upload</label> <%= file_field_tag "file" %>
# <%= submit_tag %>
@@ -85,23 +144,93 @@ module ActionView
#
# The specified URL will then be passed a File object containing the selected file, or if the field
# was left blank, a StringIO object.
+ #
+ # ==== Options
+ # * Creates standard HTML attributes for the tag.
+ # * <tt>:disabled</tt> - If set to true, the user will not be able to use this input.
+ #
+ # ==== Examples
+ # file_field_tag 'attachment'
+ # # => <input id="attachment" name="attachment" type="file" />
+ #
+ # file_field_tag 'avatar', :class => 'profile-input'
+ # # => <input class="profile-input" id="avatar" name="avatar" type="file" />
+ #
+ # file_field_tag 'picture', :disabled => true
+ # # => <input disabled="disabled" id="picture" name="picture" type="file" />
+ #
+ # file_field_tag 'resume', :value => '~/resume.doc'
+ # # => <input id="resume" name="resume" type="file" value="~/resume.doc" />
+ #
+ # file_field_tag 'user_pic', :accept => 'image/png,image/gif,image/jpeg'
+ # # => <input accept="image/png,image/gif,image/jpeg" id="user_pic" name="user_pic" type="file" />
+ #
+ # file_field_tag 'file', :accept => 'text/html', :class => 'upload', :value => 'index.html'
+ # # => <input accept="text/html" class="upload" id="file" name="file" type="file" value="index.html" />
def file_field_tag(name, options = {})
text_field_tag(name, nil, options.update("type" => "file"))
end
- # Creates a password field.
+ # Creates a password field, a masked text field that will hide the users input behind a mask character.
#
- # Takes the same options as text_field_tag
+ # ==== Options
+ # * <tt>:disabled</tt> - If set to true, the user will not be able to use this input.
+ # * <tt>:size</tt> - The number of visible characters that will fit in the input.
+ # * <tt>:maxlength</tt> - The maximum number of characters that the browser will allow the user to enter.
+ # * Any other key creates standard HTML attributes for the tag.
+ #
+ # ==== Examples
+ # password_field_tag 'pass'
+ # # => <input id="pass" name="pass" type="password" />
+ #
+ # password_field_tag 'secret', 'Your secret here'
+ # # => <input id="secret" name="secret" type="password" value="Your secret here" />
+ #
+ # password_field_tag 'masked', nil, :class => 'masked_input_field'
+ # # => <input class="masked_input_field" id="masked" name="masked" type="password" />
+ #
+ # password_field_tag 'token', '', :size => 15
+ # # => <input id="token" name="token" size="15" type="password" value="" />
+ #
+ # password_field_tag 'key', nil, :maxlength => 16
+ # # => <input id="key" maxlength="16" name="key" type="password" />
+ #
+ # password_field_tag 'confirm_pass', nil, :disabled => true
+ # # => <input disabled="disabled" id="confirm_pass" name="confirm_pass" type="password" />
+ #
+ # password_field_tag 'pin', '1234', :maxlength => 4, :size => 6, :class => "pin-input"
+ # # => <input class="pin-input" id="pin" maxlength="4" name="pin" size="6" type="password" value="1234" />
def password_field_tag(name = "password", value = nil, options = {})
text_field_tag(name, value, options.update("type" => "password"))
end
- # Creates a text input area.
+ # Creates a text input area; use a textarea for longer text inputs such as blog posts or descriptions.
+ #
+ # ==== Options
+ # * <tt>:size</tt> - A string specifying the dimensions of the textarea using dimensions (e.g., "25x10").
+ # * <tt>:rows</tt> - Specify the number of rows in the textarea
+ # * <tt>:cols</tt> - Specify the number of columns in the textarea
+ # * <tt>:disabled</tt> - If set to true, the user will not be able to use this input.
+ # * Any other key creates standard HTML attributes for the tag.
+ #
+ # ==== Examples
+ # text_area_tag 'post'
+ # # => <textarea id="post" name="post"></textarea>
+ #
+ # text_area_tag 'bio', @user.bio
+ # # => <textarea id="bio" name="bio">This is my biography.</textarea>
#
- # Options:
- # * <tt>:size</tt> - A string specifying the dimensions of the textarea.
- # # Outputs <textarea name="body" id="body" cols="25" rows="10"></textarea>
- # <%= text_area_tag "body", nil, :size => "25x10" %>
+ # text_area_tag 'body', nil, :rows => 10, :cols => 25
+ # # => <textarea cols="25" id="body" name="body" rows="10"></textarea>
+ #
+ # text_area_tag 'body', nil, :size => "25x10"
+ # # => <textarea name="body" id="body" cols="25" rows="10"></textarea>
+ #
+ # text_area_tag 'description', "Description goes here.", :disabled => true
+ # # => <textarea disabled="disabled" id="description" name="description">Description goes here.</textarea>
+ #
+ # text_area_tag 'comment', nil, :class => 'comment_input'
+ # # => <textarea class="comment_input" id="comment" name="comment"></textarea>
def text_area_tag(name, content = nil, options = {})
options.stringify_keys!
@@ -112,14 +241,52 @@ module ActionView
content_tag :textarea, content, { "name" => name, "id" => name }.update(options.stringify_keys)
end
- # Creates a check box.
+ # Creates a check box form input tag.
+ #
+ # ==== Options
+ # * <tt>:disabled</tt> - If set to true, the user will not be able to use this input.
+ # * Any other key creates standard HTML options for the tag.
+ #
+ # ==== Examples
+ # check_box_tag 'accept'
+ # # => <input id="accept" name="accept" type="checkbox" value="1" />
+ #
+ # check_box_tag 'rock', 'rock music'
+ # # => <input id="rock" name="rock" type="checkbox" value="rock music" />
+ #
+ # check_box_tag 'receive_email', 'yes', true
+ # # => <input checked="checked" id="receive_email" name="receive_email" type="checkbox" value="yes" />
+ #
+ # check_box_tag 'tos', 'yes', false, :class => 'accept_tos'
+ # # => <input class="accept_tos" id="tos" name="tos" type="checkbox" value="yes" />
+ #
+ # check_box_tag 'eula', 'accepted', false, :disabled => true
+ # # => <input disabled="disabled" id="eula" name="eula" type="checkbox" value="accepted" />
def check_box_tag(name, value = "1", checked = false, options = {})
html_options = { "type" => "checkbox", "name" => name, "id" => name, "value" => value }.update(options.stringify_keys)
html_options["checked"] = "checked" if checked
tag :input, html_options
end
- # Creates a radio button.
+ # Creates a radio button; use groups of radio buttons named the same to allow users to
+ # select from a group of options.
+ #
+ # ==== Options
+ # * <tt>:disabled</tt> - If set to true, the user will not be able to use this input.
+ # * Any other key creates standard HTML options for the tag.
+ #
+ # ==== Examples
+ # radio_button_tag 'gender', 'male'
+ # # => <input id="gender_male" name="gender" type="radio" value="male" />
+ #
+ # radio_button_tag 'receive_updates', 'no', true
+ # # => <input checked="checked" id="receive_updates_no" name="receive_updates" type="radio" value="no" />
+ #
+ # radio_button_tag 'time_slot', "3:00 p.m.", false, :disabled => true
+ # # => <input disabled="disabled" id="time_slot_300_pm" name="time_slot" type="radio" value="3:00 p.m." />
+ #
+ # radio_button_tag 'color', "green", true, :class => "color_input"
+ # # => <input checked="checked" class="color_input" id="color_green" name="color" type="radio" value="green" />
def radio_button_tag(name, value, checked = false, options = {})
pretty_tag_value = value.to_s.gsub(/\s/, "_").gsub(/(?!-)\W/, "").downcase
pretty_name = name.gsub(/\[/, "_").gsub(/\]/, "")
@@ -128,14 +295,33 @@ module ActionView
tag :input, html_options
end
- # Creates a submit button with the text <tt>value</tt> as the caption. If options contains a pair with the key of <tt>:disable_with</tt>,
- # then the value will be used to rename a disabled version of the submit button.
- #
- # Options:
- # * <tt>:disable_with</tt> - When specified the button will be disabled when clicked and the <tt>value</tt> will be replaced with the
- # the string provided.
- # # Outputs <input name="commit" onclick="this.disabled=true;this.value='Saving...';this.form.submit();" type="submit" value="Send" />
- # <%= submit_tag 'Send', :disable_with => 'Saving...' %>
+ # Creates a submit button with the text <tt>value</tt> as the caption.
+ #
+ # ==== Options
+ # * <tt>:disabled</tt> - If set to true, the user will not be able to use this input.
+ # * <tt>:disable_with</tt> - Value of this parameter will be used as the value for a disabled version
+ # of the submit button when the form is submitted.
+ # * Any other key creates standard HTML options for the tag.
+ #
+ # ==== Examples
+ # submit_tag
+ # # => <input name="commit" type="submit" value="Save changes" />
+ #
+ # submit_tag "Edit this article"
+ # # => <input name="commit" type="submit" value="Edit this article" />
+ #
+ # submit_tag "Save edits", :disabled => true
+ # # => <input disabled="disabled" name="commit" type="submit" value="Save edits" />
+ #
+ # submit_tag "Complete sale", :disable_with => "Please wait..."
+ # # => <input name="commit" onclick="this.disabled=true;this.value='Please wait...';this.form.submit();"
+ # # type="submit" value="Complete sale" />
+ #
+ # submit_tag nil, :class => "form_submit"
+ # # => <input class="form_submit" name="commit" type="submit" />
+ #
+ # submit_tag "Edit", :disable_width => "Editing...", :class => 'edit-button'
+ # # => <input class="edit-button" disable_width="Editing..." name="commit" type="submit" value="Edit" />
def submit_tag(value = "Save changes", options = {})
options.stringify_keys!
@@ -157,6 +343,23 @@ module ActionView
# Displays an image which when clicked will submit the form.
#
# <tt>source</tt> is passed to AssetTagHelper#image_path
+ #
+ # ==== Options
+ # * <tt>:disabled</tt> - If set to true, the user will not be able to use this input.
+ # * Any other key creates standard HTML options for the tag.
+ #
+ # ==== Examples
+ # image_submit_tag("login.png")
+ # # => <input src="/images/login.png" type="image" />
+ #
+ # image_submit_tag("purchase.png"), :disabled => true
+ # # => <input disabled="disabled" src="/images/purchase.png" type="image" />
+ #
+ # image_submit_tag("search.png"), :class => 'search-button'
+ # # => <input class="search-button" src="/images/search.png" type="image" />
+ #
+ # image_submit_tag("agree.png"), :disabled => true, :class => "agree-disagree-button"
+ # # => <input class="agree-disagree-button" disabled="disabled" src="/images/agree.png" type="image" />
def image_submit_tag(source, options = {})
tag :input, { "type" => "image", "src" => image_path(source) }.update(options.stringify_keys)
end
diff --git a/actionpack/lib/action_view/helpers/number_helper.rb b/actionpack/lib/action_view/helpers/number_helper.rb
index 90ff164a5d..e2db853f93 100644
--- a/actionpack/lib/action_view/helpers/number_helper.rb
+++ b/actionpack/lib/action_view/helpers/number_helper.rb
@@ -4,19 +4,25 @@ module ActionView
# Methods are provided for phone numbers, currency, percentage,
# precision, positional notation, and file size.
module NumberHelper
- # Formats a +number+ into a US phone number. You can customize the format
+ # Formats a +number+ into a US phone number (e.g., (555) 123-9876). You can customize the format
# in the +options+ hash.
+ #
+ # ==== Options
# * <tt>:area_code</tt> - Adds parentheses around the area code.
- # * <tt>:delimiter</tt> - Specifies the delimiter to use, defaults to "-".
+ # * <tt>:delimiter</tt> - Specifies the delimiter to use (defaults to "-").
# * <tt>:extension</tt> - Specifies an extension to add to the end of the
- # generated number
+ # generated number.
# * <tt>:country_code</tt> - Sets the country code for the phone number.
#
- # number_to_phone(1235551234) => 123-555-1234
- # number_to_phone(1235551234, :area_code => true) => (123) 555-1234
- # number_to_phone(1235551234, :delimiter => " ") => 123 555 1234
- # number_to_phone(1235551234, :area_code => true, :extension => 555) => (123) 555-1234 x 555
- # number_to_phone(1235551234, :country_code => 1)
+ # ==== Examples
+ # number_to_phone(1235551234) # => 123-555-1234
+ # number_to_phone(1235551234, :area_code => true) # => (123) 555-1234
+ # number_to_phone(1235551234, :delimiter => " ") # => 123 555 1234
+ # number_to_phone(1235551234, :area_code => true, :extension => 555) # => (123) 555-1234 x 555
+ # number_to_phone(1235551234, :country_code => 1) # => +1-123-555-1234
+ #
+ # number_to_phone(1235551234, :country_code => 1, :extension => 1343, :delimeter => ".")
+ # => +1.123.555.1234 x 1343
def number_to_phone(number, options = {})
number = number.to_s.strip unless number.nil?
options = options.stringify_keys
@@ -40,18 +46,22 @@ module ActionView
end
end
- # Formats a +number+ into a currency string. You can customize the format
+ # Formats a +number+ into a currency string (e.g., $13.65). You can customize the format
# in the +options+ hash.
- # * <tt>:precision</tt> - Sets the level of precision, defaults to 2
- # * <tt>:unit</tt> - Sets the denomination of the currency, defaults to "$"
- # * <tt>:separator</tt> - Sets the separator between the units, defaults to "."
- # * <tt>:delimiter</tt> - Sets the thousands delimiter, defaults to ","
#
- # number_to_currency(1234567890.50) => $1,234,567,890.50
- # number_to_currency(1234567890.506) => $1,234,567,890.51
- # number_to_currency(1234567890.506, :precision => 3) => $1,234,567,890.506
+ # ==== Options
+ # * <tt>:precision</tt> - Sets the level of precision (defaults to 2).
+ # * <tt>:unit</tt> - Sets the denomination of the currency (defaults to "$").
+ # * <tt>:separator</tt> - Sets the separator between the units (defaults to ".").
+ # * <tt>:delimiter</tt> - Sets the thousands delimiter (defaults to ",").
+ #
+ # ==== Examples
+ # number_to_currency(1234567890.50) # => $1,234,567,890.50
+ # number_to_currency(1234567890.506) # => $1,234,567,890.51
+ # number_to_currency(1234567890.506, :precision => 3) # => $1,234,567,890.506
+ #
# number_to_currency(1234567890.50, :unit => "&pound;", :separator => ",", :delimiter => "")
- # => &pound;1234567890,50
+ # # => &pound;1234567890,50
def number_to_currency(number, options = {})
options = options.stringify_keys
precision = options["precision"] || 2
@@ -67,14 +77,19 @@ module ActionView
end
end
- # Formats a +number+ as a percentage string. You can customize the
+ # Formats a +number+ as a percentage string (e.g., 65%). You can customize the
# format in the +options+ hash.
- # * <tt>:precision</tt> - Sets the level of precision, defaults to 3
- # * <tt>:separator</tt> - Sets the separator between the units, defaults to "."
#
- # number_to_percentage(100) => 100.000%
- # number_to_percentage(100, {:precision => 0}) => 100%
- # number_to_percentage(302.0574, {:precision => 2}) => 302.06%
+ # ==== Options
+ # * <tt>:precision</tt> - Sets the level of precision (defaults to 3).
+ # * <tt>:separator</tt> - Sets the separator between the units (defaults to ".").
+ #
+ # ==== Examples
+ # number_to_percentage(100) # => 100.000%
+ # number_to_percentage(100, :precision => 0) # => 100%
+ #
+ # number_to_percentage(302.24398923423, :precision => 5)
+ # # => 302.24399%
def number_to_percentage(number, options = {})
options = options.stringify_keys
precision = options["precision"] || 3
@@ -93,14 +108,20 @@ module ActionView
end
end
- # Formats a +number+ with grouped thousands using +delimiter+. You
+ # Formats a +number+ with grouped thousands using +delimiter+ (e.g., 12,324). You
# can customize the format using optional <em>delimiter</em> and <em>separator</em> parameters.
- # * <tt>delimiter</tt> - Sets the thousands delimiter, defaults to ","
- # * <tt>separator</tt> - Sets the separator between the units, defaults to "."
#
- # number_with_delimiter(12345678) => 12,345,678
- # number_with_delimiter(12345678.05) => 12,345,678.05
- # number_with_delimiter(12345678, ".") => 12.345.678
+ # ==== Options
+ # * <tt>delimiter</tt> - Sets the thousands delimiter (defaults to ",").
+ # * <tt>separator</tt> - Sets the separator between the units (defaults to ".").
+ #
+ # ==== Examples
+ # number_with_delimiter(12345678) # => 12,345,678
+ # number_with_delimiter(12345678.05) # => 12,345,678.05
+ # number_with_delimiter(12345678, ".") # => 12.345.678
+ #
+ # number_with_delimiter(98765432.98, " ", ",")
+ # # => 98 765 432,98
def number_with_delimiter(number, delimiter=",", separator=".")
begin
parts = number.to_s.split('.')
@@ -111,29 +132,35 @@ module ActionView
end
end
- # Formats a +number+ with the specified level of +precision+. The default
+ # Formats a +number+ with the specified level of +precision+ (e.g., 112.32 has a precision of 2). The default
# level of precision is 3.
#
- # number_with_precision(111.2345) => 111.235
- # number_with_precision(111.2345, 2) => 111.24
+ # ==== Examples
+ # number_with_precision(111.2345) # => 111.235
+ # number_with_precision(111.2345, 2) # => 111.24
+ # number_with_precision(13, 5) # => 13.00000
+ # number_with_precision(389.32314, 0) # => 389
def number_with_precision(number, precision=3)
"%01.#{precision}f" % number
rescue
number
end
- # Formats the bytes in +size+ into a more understandable representation.
- # Useful for reporting file sizes to users. This method returns nil if
+ # Formats the bytes in +size+ into a more understandable representation
+ # (e.g., giving it 1500 yields 1.5 KB). This method is useful for
+ # reporting file sizes to users. This method returns nil if
# +size+ cannot be converted into a number. You can change the default
- # precision of 1 in +precision+.
+ # precision of 1 using the precision parameter +precision+.
#
- # number_to_human_size(123) => 123 Bytes
- # number_to_human_size(1234) => 1.2 KB
- # number_to_human_size(12345) => 12.1 KB
- # number_to_human_size(1234567) => 1.2 MB
- # number_to_human_size(1234567890) => 1.1 GB
- # number_to_human_size(1234567890123) => 1.1 TB
- # number_to_human_size(1234567, 2) => 1.18 MB
+ # ==== Examples
+ # number_to_human_size(123) # => 123 Bytes
+ # number_to_human_size(1234) # => 1.2 KB
+ # number_to_human_size(12345) # => 12.1 KB
+ # number_to_human_size(1234567) # => 1.2 MB
+ # number_to_human_size(1234567890) # => 1.1 GB
+ # number_to_human_size(1234567890123) # => 1.1 TB
+ # number_to_human_size(1234567, 2) # => 1.18 MB
+ # number_to_human_size(483989, 0) # => 4 MB
def number_to_human_size(size, precision=1)
size = Kernel.Float(size)
case
diff --git a/actionpack/lib/action_view/helpers/tag_helper.rb b/actionpack/lib/action_view/helpers/tag_helper.rb
index 7c6903220a..8d3f6be04c 100644
--- a/actionpack/lib/action_view/helpers/tag_helper.rb
+++ b/actionpack/lib/action_view/helpers/tag_helper.rb
@@ -3,7 +3,7 @@ require 'erb'
module ActionView
module Helpers #:nodoc:
- # Use these methods to generate HTML tags programmatically when you can't use
+ # Provides methods to generate HTML tags programmatically when you can't use
# a Builder. By default, they output XHTML compliant tags.
module TagHelper
include ERB::Util
@@ -11,25 +11,40 @@ module ActionView
# Returns an empty HTML tag of type +name+ which by default is XHTML
# compliant. Setting +open+ to true will create an open tag compatible
# with HTML 4.0 and below. Add HTML attributes by passing an attributes
- # hash to +options+. For attributes with no value like (disabled and
- # readonly), give it a value of true in the +options+ hash. You can use
+ # hash to +options+.
+ #
+ # ==== Options
+ # The +options+ hash is used with attributes with no value like (<tt>disabled</tt> and
+ # <tt>readonly</tt>), which you can give a value of true in the +options+ hash. You can use
# symbols or strings for the attribute names.
#
+ # ==== Examples
# tag("br")
- # # => <br />
+ # # => <br />
+ #
# tag("br", nil, true)
- # # => <br>
+ # # => <br>
+ #
# tag("input", { :type => 'text', :disabled => true })
- # # => <input type="text" disabled="disabled" />
+ # # => <input type="text" disabled="disabled" />
+ #
+ # tag("img", { :src => "open.png" })
+ # # => <img src="open.png" />
def tag(name, options = nil, open = false)
"<#{name}#{tag_options(options) if options}" + (open ? ">" : " />")
end
# Returns an HTML block tag of type +name+ surrounding the +content+. Add
- # HTML attributes by passing an attributes hash to +options+. For attributes
- # with no value like (disabled and readonly), give it a value of true in
- # the +options+ hash. You can use symbols or strings for the attribute names.
+ # 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.
#
+ # ==== Options
+ # The +options+ hash is used with attributes with no value like (<tt>disabled</tt> and
+ # <tt>readonly</tt>), 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!")
# # => <p>Hello world!</p>
# content_tag(:div, content_tag(:p, "Hello world!"), :class => "strong")
@@ -37,9 +52,6 @@ module ActionView
# content_tag("select", options, :multiple => true)
# # => <select multiple="multiple">...options...</select>
#
- # 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.
- #
# <% content_tag :div, :class => "strong" do -%>
# Hello world!
# <% end -%>
@@ -61,16 +73,24 @@ module ActionView
# otherwise be recognized as markup. CDATA sections begin with the string
# <tt><![CDATA[</tt> and end with (and may not contain) the string <tt>]]></tt>.
#
+ # ==== Examples
# cdata_section("<hello world>")
- # # => <![CDATA[<hello world>]]>
+ # # => <![CDATA[<hello world>]]>
+ #
+ # cdata_section(File.read("hello_world.txt"))
+ # # => <![CDATA[<hello from a text file]]>
def cdata_section(content)
"<![CDATA[#{content}]]>"
end
- # Returns the escaped +html+ without affecting existing escaped entities.
+ # Returns an escaped version of +html+ without affecting existing escaped entities.
#
+ # ==== Examples
# escape_once("1 > 2 &amp; 3")
- # # => "1 &lt; 2 &amp; 3"
+ # # => "1 &lt; 2 &amp; 3"
+ #
+ # escape_once("&lt;&lt; Accept & Checkout")
+ # # => "&lt;&lt; Accept &amp; Checkout"
def escape_once(html)
fix_double_escape(html_escape(html.to_s))
end
diff --git a/actionpack/lib/action_view/helpers/text_helper.rb b/actionpack/lib/action_view/helpers/text_helper.rb
index d986233796..8db8ce7009 100644
--- a/actionpack/lib/action_view/helpers/text_helper.rb
+++ b/actionpack/lib/action_view/helpers/text_helper.rb
@@ -3,35 +3,48 @@ require 'html/document'
module ActionView
module Helpers #:nodoc:
- # The TextHelper Module provides a set of methods for filtering, formatting
- # and transforming strings that can reduce the amount of inline Ruby code in
+ # The TextHelper module provides a set of methods for filtering, formatting
+ # and transforming strings, which can reduce the amount of inline Ruby code in
# your views. These helper methods extend ActionView making them callable
- # within your template files as shown in the following example which truncates
- # the title of each post to 10 characters.
- #
- # <% @posts.each do |post| %>
- # # post == 'This is my title'
- # Title: <%= truncate(post.title, 10) %>
- # <% end %>
- # => Title: This is my...
+ # within your template files.
module TextHelper
# The preferred method of outputting text in your views is to use the
# <%= "text" %> eRuby syntax. The regular _puts_ and _print_ methods
# do not operate as expected in an eRuby code block. If you absolutely must
- # output text within a code block, you can use the concat method.
+ # output text within a non-output code block (i.e., <% %>), you can use the concat method.
#
- # <% concat "hello", binding %>
- # is equivalent to using:
- # <%= "hello" %>
+ # ==== Examples
+ # <%
+ # concat "hello", binding
+ # # is the equivalent of <%= "hello" %>
+ #
+ # if (logged_in == true):
+ # concat "Logged in!", binding
+ # else
+ # concat link_to('login', :action => login), binding
+ # end
+ # # will either display "Logged in!" or a login link
+ # %>
def concat(string, binding)
eval(ActionView::Base.erb_variable, binding) << string
end
# If +text+ is longer than +length+, +text+ will be truncated to the length of
- # +length+ and the last three characters will be replaced with the +truncate_string+.
+ # +length+ (defaults to 30) and the last three characters will be replaced with the +truncate_string+
+ # (defaults to "...").
#
+ # ==== Examples
# truncate("Once upon a time in a world far far away", 14)
- # => Once upon a...
+ # # => Once upon a...
+ #
+ # truncate("Once upon a time in a world far far away")
+ # # => Once upon a time in a world f...
+ #
+ # truncate("And they found that many people were sleeping better.", 25, "(clipped)")
+ # # => And they found that many (clipped)
+ #
+ # truncate("And they found that many people were sleeping better.", 15, "... (continued)")
+ # # => And they found... (continued)
def truncate(text, length = 30, truncate_string = "...")
if text.nil? then return end
l = length - truncate_string.chars.length
@@ -40,13 +53,21 @@ module ActionView
# Highlights one or more +phrases+ everywhere in +text+ by inserting it into
# a +highlighter+ string. The highlighter can be specialized by passing +highlighter+
- # as a single-quoted string with \1 where the phrase is to be inserted.
+ # as a single-quoted string with \1 where the phrase is to be inserted (defaults to
+ # '<strong class="highlight">\1</strong>')
#
+ # ==== Examples
# highlight('You searched for: rails', 'rails')
# # => You searched for: <strong class="highlight">rails</strong>
#
+ # highlight('You searched for: ruby, rails, dhh', 'actionpack')
+ # # => You searched for: ruby, rails, dhh
+ #
# highlight('You searched for: rails', ['for', 'rails'], '<em>\1</em>')
# # => You searched <em>for</em>: <em>rails</em>
+ #
+ # highlight('You searched for: rails', 'rails', "<a href='search?q=\1'>\1</a>")
+ # # => You searched for: <a href='search?q=rails>rails</a>
def highlight(text, phrases, highlighter = '<strong class="highlight">\1</strong>')
if text.blank? || phrases.blank?
text
@@ -57,16 +78,26 @@ module ActionView
end
# Extracts an excerpt from +text+ that matches the first instance of +phrase+.
- # The +radius+ expands the excerpt on each side of +phrase+ by the number of characters
- # defined in +radius+. If the excerpt radius overflows the beginning or end of the +text+,
+ # The +radius+ expands the excerpt on each side of the first occurance of +phrase+ by the number of characters
+ # defined in +radius+ (which defaults to 100). If the excerpt radius overflows the beginning or end of the +text+,
# then the +excerpt_string+ will be prepended/appended accordingly. If the +phrase+
# isn't found, nil is returned.
#
+ # ==== Examples
# excerpt('This is an example', 'an', 5)
- # => "...s is an examp..."
+ # # => "...s is an examp..."
#
# excerpt('This is an example', 'is', 5)
- # => "This is an..."
+ # # => "This is an..."
+ #
+ # excerpt('This is an example', 'is')
+ # # => "This is an example"
+ #
+ # excerpt('This next thing is an example', 'ex', 2)
+ # # => "...next t..."
+ #
+ # excerpt('This is also an example', 'an', 8, '<chop> ')
+ # # => "<chop> is also an example"
def excerpt(text, phrase, radius = 100, excerpt_string = "...")
if text.nil? || phrase.nil? then return end
phrase = Regexp.escape(phrase)
@@ -89,9 +120,18 @@ module ActionView
# is loaded, it will use the Inflector to determine the plural form, otherwise
# it will just add an 's' to the +singular+ word.
#
- # pluralize(1, 'person') => 1 person
- # pluralize(2, 'person') => 2 people
- # pluralize(3, 'person', 'users') => 3 users
+ # ==== Examples
+ # pluralize(1, 'person')
+ # # => 1 person
+ #
+ # pluralize(2, 'person')
+ # # => 2 people
+ #
+ # pluralize(3, 'person', 'users')
+ # # => 3 users
+ #
+ # pluralize(0, 'person')
+ # # => 0 people
def pluralize(count, singular, plural = nil)
"#{count || 0} " + if count == 1 || count == '1'
singular
@@ -105,10 +145,21 @@ module ActionView
end
# Wraps the +text+ into lines no longer than +line_width+ width. This method
- # breaks on the first whitespace character that does not exceed +line_width+.
+ # breaks on the first whitespace character that does not exceed +line_width+
+ # (which is 80 by default).
#
+ # ==== Examples
# word_wrap('Once upon a time', 4)
- # => Once\nupon\na\ntime
+ # # => Once\nupon\na\ntime
+ #
+ # word_wrap('Once upon a time', 8)
+ # # => Once upon\na time
+ #
+ # word_wrap('Once upon a time')
+ # # => Once upon a time
+ #
+ # word_wrap('Once upon a time', 1)
+ # # => Once\nupon\na\ntime
def word_wrap(text, line_width = 80)
text.gsub(/\n/, "\n\n").gsub(/(.{1,#{line_width}})(\s+|$)/, "\\1\n").strip
end
@@ -116,9 +167,24 @@ module ActionView
begin
require_library_or_gem "redcloth" unless Object.const_defined?(:RedCloth)
- # Returns the text with all the Textile codes turned into HTML tags.
+ # Returns the text with all the Textile[http://www.textism.com/tools/textile] codes turned into HTML tags.
+ #
+ # You can learn more about Textile's syntax at its website[http://www.textism.com/tools/textile].
# <i>This method is only available if RedCloth[http://whytheluckystiff.net/ruby/redcloth/]
# is available</i>.
+ #
+ # ==== Examples
+ # textilize("*This is Textile!* Rejoice!")
+ # # => "<p><strong>This is Textile!</strong> Rejoice!</p>"
+ #
+ # textilize("I _love_ ROR(Ruby on Rails)!")
+ # # => "<p>I <em>love</em> <acronym title="Ruby on Rails">ROR</acronym>!</p>"
+ #
+ # textilize("h2. Textile makes markup -easy- simple!")
+ # # => "<h2>Textile makes markup <del>easy</del> simple!</h2>"
+ #
+ # textilize("Visit the Rails website "here":http://www.rubyonrails.org/.)
+ # # => "<p>Visit the Rails website <a href="http://www.rubyonrails.org/">here</a>.</p>"
def textilize(text)
if text.blank?
""
@@ -131,8 +197,23 @@ module ActionView
# Returns the text with all the Textile codes turned into HTML tags,
# but without the bounding <p> tag that RedCloth adds.
+ #
+ # You can learn more about Textile's syntax at its website[http://www.textism.com/tools/textile].
# <i>This method is only available if RedCloth[http://whytheluckystiff.net/ruby/redcloth/]
# is available</i>.
+ #
+ # ==== Examples
+ # textilize_without_paragraph("*This is Textile!* Rejoice!")
+ # # => "<strong>This is Textile!</strong> Rejoice!"
+ #
+ # textilize_without_paragraph("I _love_ ROR(Ruby on Rails)!")
+ # # => "I <em>love</em> <acronym title="Ruby on Rails">ROR</acronym>!"
+ #
+ # textilize_without_paragraph("h2. Textile makes markup -easy- simple!")
+ # # => "<h2>Textile makes markup <del>easy</del> simple!</h2>"
+ #
+ # textilize_without_paragraph("Visit the Rails website "here":http://www.rubyonrails.org/.)
+ # # => "Visit the Rails website <a href="http://www.rubyonrails.org/">here</a>."
def textilize_without_paragraph(text)
textiled = textilize(text)
if textiled[0..2] == "<p>" then textiled = textiled[3..-1] end
@@ -149,6 +230,20 @@ module ActionView
# Returns the text with all the Markdown codes turned into HTML tags.
# <i>This method is only available if BlueCloth[http://www.deveiate.org/projects/BlueCloth]
# is available</i>.
+ #
+ # ==== Examples
+ # markdown("We are using __Markdown__ now!")
+ # # => "<p>We are using <strong>Markdown</strong> now!</p>"
+ #
+ # markdown("We like to _write_ `code`, not just _read_ it!")
+ # # => "<p>We like to <em>write</em> <code>code</code>, not just <em>read</em> it!</p>"
+ #
+ # markdown("The [Markdown website](http://daringfireball.net/projects/markdown/) has more information.")
+ # # => "<p>The <a href="http://daringfireball.net/projects/markdown/">Markdown website</a>
+ # # has more information.</p>"
+ #
+ # markdown('![The ROR logo](http://rubyonrails.com/images/rails.png "Ruby on Rails")')
+ # # => '<p><img src="http://rubyonrails.com/images/rails.png" alt="The ROR logo" title="Ruby on Rails" /></p>'
def markdown(text)
text.blank? ? "" : BlueCloth.new(text).to_html
end
@@ -161,6 +256,20 @@ module ActionView
# paragraph and wrapped in <tt><p></tt> tags. One newline (<tt>\n</tt>) is
# considered as a linebreak and a <tt><br /></tt> tag is appended. This
# method does not remove the newlines from the +text+.
+ #
+ # ==== Examples
+ # my_text = """Here is some basic text...
+ # ...with a line break."""
+ #
+ # simple_format(my_text)
+ # # => "<p>Here is some basic text...<br />...with a line break.</p>"
+ #
+ # more_text = """We want to put a paragraph...
+ #
+ # ...right there."""
+ #
+ # simple_format(more_text)
+ # # => "<p>We want to put a paragraph...</p><p>...right there.</p>"
def simple_format(text)
content_tag 'p', text.to_s.
gsub(/\r\n?/, "\n"). # \r\n and \r -> \n
@@ -168,21 +277,31 @@ module ActionView
gsub(/([^\n]\n)(?=[^\n])/, '\1<br />') # 1 newline -> br
end
- # Turns all urls and email addresses into clickable links. The +link+ parameter
- # will limit what should be linked. You can add html attributes to the links using
+ # Turns all URLs and e-mail addresses into clickable links. The +link+ parameter
+ # will limit what should be linked. You can add HTML attributes to the links using
# +href_options+. Options for +link+ are <tt>:all</tt> (default),
- # <tt>:email_addresses</tt>, and <tt>:urls</tt>.
+ # <tt>:email_addresses</tt>, and <tt>:urls</tt>. If a block is given, each URL and
+ # e-mail address is yielded and the result is used as the link text.
+ #
+ # ==== Examples
+ # auto_link("Go to http://www.rubyonrails.org and say hello to david@loudthinking.com")
+ # # => "Go to <a href="http://www.rubyonrails.org">http://www.rubyonrails.org</a> and
+ # # say hello to <a href="mailto:david@loudthinking.com">david@loudthinking.com</a>"
#
- # auto_link("Go to http://www.rubyonrails.org and say hello to david@loudthinking.com") =>
- # Go to <a href="http://www.rubyonrails.org">http://www.rubyonrails.org</a> and
- # say hello to <a href="mailto:david@loudthinking.com">david@loudthinking.com</a>
+ # auto_link("Visit http://www.loudthinking.com/ or e-mail david@loudthinking.com", :urls)
+ # # => "Visit <a href=\"http://www.loudthinking.com/\">http://www.loudthinking.com/</a>
+ # # or e-mail david@loudthinking.com"
#
- # If a block is given, each url and email address is yielded and the
- # result is used as the link text.
+ # auto_link("Visit http://www.loudthinking.com/ or e-mail david@loudthinking.com", :email_addresses)
+ # # => "Visit http://www.loudthinking.com/ or e-mail <a href=\"mailto:david@loudthinking.com\">david@loudthinking.com</a>"
#
- # auto_link(post.body, :all, :target => '_blank') do |text|
+ # post_body = "Welcome to my new blog at http://www.myblog.com/. Please e-mail me at me@email.com."
+ # auto_link(post_body, :all, :target => '_blank') do |text|
# truncate(text, 15)
# end
+ # # => "Welcome to my new blog at <a href=\"http://www.myblog.com/\" target=\"_blank\">http://www.m...</a>.
+ # Please e-mail me at <a href=\"mailto:me@email.com\">me@email.com</a>."
+ #
def auto_link(text, link = :all, href_options = {}, &block)
return '' if text.blank?
case link
@@ -192,10 +311,17 @@ module ActionView
end
end
- # Strips link tags from +text+ leaving just the link label.
+ # Strips all link tags from +text+ leaving just the link text.
#
+ # ==== Examples
# strip_links('<a href="http://www.rubyonrails.org">Ruby on Rails</a>')
- # => Ruby on Rails
+ # # => Ruby on Rails
+ #
+ # strip_links('Please e-mail me at <a href="mailto:me@email.com">me@email.com</a>.')
+ # # => Please e-mail me at me@email.com.
+ #
+ # strip_links('Blog: <a href="http://www.myblog.com/" class="nav" target=\"_blank\">Visit</a>.')
+ # # => Blog: Visit
def strip_links(text)
text.gsub(/<a\b.*?>(.*?)<\/a>/mi, '\1')
end
@@ -204,15 +330,23 @@ module ActionView
VERBOTEN_ATTRS = /^on/i unless defined?(VERBOTEN_ATTRS)
# Sanitizes the +html+ by converting <form> and <script> tags into regular
- # text, and removing all "onxxx" attributes (so that arbitrary Javascript
- # cannot be executed). It also removes href= and src= attributes that start with
+ # text, and removing all "on*" (e.g., onClick) attributes so that arbitrary Javascript
+ # cannot be executed. It also removes <tt>href</tt> and <tt>src</tt> attributes that start with
# "javascript:". You can modify what gets sanitized by defining VERBOTEN_TAGS
# and VERBOTEN_ATTRS before this Module is loaded.
#
+ # ==== Examples
# sanitize('<script> do_nasty_stuff() </script>')
- # => &lt;script> do_nasty_stuff() &lt;/script>
+ # # => &lt;script> do_nasty_stuff() &lt;/script>
+ #
# sanitize('<a href="javascript: sucker();">Click here for $100</a>')
- # => <a>Click here for $100</a>
+ # # => <a>Click here for $100</a>
+ #
+ # sanitize('<a href="#" onClick="kill_all_humans();">Click here!!!</a>')
+ # # => <a href="#">Click here!!!</a>
+ #
+ # sanitize('<img src="javascript:suckers_run_this();" />')
+ # # => <img />
def sanitize(html)
# only do this if absolutely necessary
if html.index("<")
@@ -248,6 +382,16 @@ module ActionView
# Strips all HTML tags from the +html+, including comments. This uses the
# html-scanner tokenizer and so its HTML parsing ability is limited by
# that of html-scanner.
+ #
+ # ==== Examples
+ # strip_tags("Strip <i>these</i> tags!")
+ # # => Strip these tags!
+ #
+ # strip_tags("<b>Bold</b> no more! <a href='more.html'>See more here</a>...")
+ # # => Bold no more! See more here...
+ #
+ # strip_tags("<div id='top-bar'>Welcome to my website!</div>")
+ # # => Welcome to my website!
def strip_tags(html)
return html if html.blank?
if html.index("<")
@@ -269,25 +413,34 @@ module ActionView
# Creates a Cycle object whose _to_s_ method cycles through elements of an
# array every time it is called. This can be used for example, to alternate
- # classes for table rows:
+ # classes for table rows. You can use named cycles to allow nesting in loops.
+ # Passing a Hash as the last parameter with a <tt>:name</tt> key will create a
+ # named cycle. You can manually reset a cycle by calling reset_cycle and passing the
+ # name of the cycle.
#
+ # ==== Examples
+ # # Alternate CSS classes for even and odd numbers...
+ # @items = [1,2,3,4]
+ # <table>
# <% @items.each do |item| %>
# <tr class="<%= cycle("even", "odd") -%>">
# <td>item</td>
# </tr>
# <% end %>
+ # </table>
#
- # You can use named cycles to allow nesting in loops. Passing a Hash as
- # the last parameter with a <tt>:name</tt> key will create a named cycle.
- # You can manually reset a cycle by calling reset_cycle and passing the
- # name of the cycle.
#
+ # # Cycle CSS classes for rows, and text colors for values within each row
+ # @items = x = [{:first => 'Robert', :middle => 'Daniel', :last => 'James'},
+ # {:first => 'Emily', :middle => 'Shannon', :maiden => 'Pike', :last => 'Hicks'},
+ # {:first => 'June', :middle => 'Dae', :last => 'Jones'}]
# <% @items.each do |item| %>
# <tr class="<%= cycle("even", "odd", :name => "row_class")
# <td>
# <% item.values.each do |value| %>
+ # <!-- Create a named cycle "colors" -->
# <span style="color:<%= cycle("red", "green", "blue", :name => "colors") -%>">
- # value
+ # <%= value %>
# </span>
# <% end %>
# <% reset_cycle("colors") %>
@@ -312,6 +465,23 @@ module ActionView
# Resets a cycle so that it starts from the first element the next time
# it is called. Pass in +name+ to reset a named cycle.
+ #
+ # ==== Example
+ # # Alternate CSS classes for even and odd numbers...
+ # @items = [[1,2,3,4], [5,6,3], [3,4,5,6,7,4]]
+ # <table>
+ # <% @items.each do |item| %>
+ # <tr class="<%= cycle("even", "odd") -%>">
+ # <% item.each do |value| %>
+ # <span style="color:<%= cycle("#333", "#666", "#999", :name => "colors") -%>">
+ # <%= value %>
+ # </span>
+ # <% end %>
+ #
+ # <% reset_cycle("colors") %>
+ # </tr>
+ # <% end %>
+ # </table>
def reset_cycle(name = "default")
cycle = get_cycle(name)
cycle.reset unless cycle.nil?