module Merb # The ViewContextMixin module provides a number of helper methods to views for # linking to assets and other pages, dealing with JavaScript, and caching. module ViewContextMixin include Merb::Assets::AssetHelpers # :section: Accessing Assets # Merb provides views with convenience methods for links images and other assets. # Creates a link for the URL given in +url+ with the text in +name+; HTML options are given in the +opts+ # hash. # # ==== Options # The +opts+ hash is used to set HTML attributes on the tag. # # ==== Examples # link_to("The Merb home page", "http://www.merbivore.com/") # # => The Merb home page # # link_to("The Ruby home page", "http://www.ruby-lang.org", {'class' => 'special', 'target' => 'blank'}) # # => The Ruby home page # # link_to p.title, "/blog/show/#{p.id}" # # => The Entry Title # def link_to(name, url='', opts={}) opts[:href] ||= url %{#{name}} end # Creates an image tag with the +src+ attribute set to the +img+ argument. The path # prefix defaults to /images/. The path prefix can be overriden by setting a +:path+ # parameter in the +opts+ hash. The rest of the +opts+ hash sets HTML attributes. # # ==== Options # path:: Sets the path prefix for the image (defaults to +/images/+) # # All other options in +opts+ set HTML attributes on the tag. # # ==== Examples # image_tag('foo.gif') # # => # # image_tag('foo.gif', :class => 'bar') # # => # # image_tag('foo.gif', :path => '/files/') # # => # # image_tag('http://test.com/foo.gif') # # => def image_tag(img, opts={}) opts[:path] ||= if img =~ %r{^https?://} '' else if Merb::Config[:path_prefix] Merb::Config[:path_prefix] + '/images/' else '/images/' end end opts[:src] ||= opts.delete(:path) + img %{} end # :section: JavaScript related functions # # Escapes text for use in JavaScript, replacing unsafe strings with their # escaped equivalent. # # ==== Examples # escape_js("'Lorem ipsum!' -- Some guy") # # => "\\'Lorem ipsum!\\' -- Some guy" # # escape_js("Please keep text\nlines as skinny\nas possible.") # # => "Please keep text\\nlines as skinny\\nas possible." def escape_js(javascript) (javascript || '').gsub('\\','\0\0').gsub(/\r\n|\n|\r/, "\\n").gsub(/["']/) { |m| "\\#{m}" } end # Creates a link tag with the text in +name+ and the onClick handler set to a JavaScript # string in +function+. # # ==== Examples # link_to_function('Click me', "alert('hi!')") # # => Click me # # link_to_function('Add to cart', "item_total += 1; alert('Item added!');") # # => Add to cart # def link_to_function(name, function) %{#{name}} end # The js method simply calls +to_json+ on an object in +data+; if the object # does not implement a +to_json+ method, then it calls +to_json+ on # +data.inspect+. # # ==== Examples # js({'user' => 'Lewis', 'page' => 'home'}) # # => "{\"user\":\"Lewis\",\"page\":\"home\"}" # # my_array = [1, 2, {"a"=>3.141}, false, true, nil, 4..10] # js(my_array) # # => "[1,2,{\"a\":3.141},false,true,null,\"4..10\"]" # def js(data) if data.respond_to? :to_json data.to_json else data.inspect.to_json end end # :section: External JavaScript and Stylesheets # # You can use require_js(:prototype) or require_css(:shinystyles) # from any view or layout, and the scripts will only be included once # in the head of the final page. To get this effect, the head of your layout you will # need to include a call to include_required_js and include_required_css. # # ==== Examples # # File: app/views/layouts/application.html.erb # # #
# <%= include_required_js %> # <%= include_required_css %> # # # <%= catch_content :layout %> # # # # # File: app/views/whatever/_part1.herb # # <% require_js 'this' -%> # <% require_css 'that', 'another_one' -%> # # # File: app/views/whatever/_part2.herb # # <% require_js 'this', 'something_else' -%> # <% require_css 'that' -%> # # # File: app/views/whatever/index.herb # # <%= partial(:part1) %> # <%= partial(:part2) %> # # # Will generate the following in the final page... # # # # # # # # . # . # . # # # See each method's documentation for more information. # :section: Bundling Asset Files # # The key to making a fast web application is to reduce both the amount of # data transfered and the number of client-server interactions. While having # many small, module Javascript or stylesheet files aids in the development # process, your web application will benefit from bundling those assets in # the production environment. # # An asset bundle is a set of asset files which are combined into a single # file. This reduces the number of requests required to render a page, and # can reduce the amount of data transfer required if you're using gzip # encoding. # # Asset bundling is always enabled in production mode, and can be optionally # enabled in all environments by setting the :bundle_assets value # in config/merb.yml to +true+. # # ==== Examples # # In the development environment, this: # # js_include_tag :prototype, :lowpro, :bundle => true # # will produce two # # <% require_js 'jquery', 'effects' %> # # A subsequent call to include_required_js will render... # # => # # # def require_js(*js) @required_js ||= [] @required_js |= js end # The require_css method can be used to require any CSS # file anywhere in your templates. Regardless of how many times # a single stylesheet is included with require_css, Merb will only include # it once in the header. # # ==== Examples # <% require_css('style') %> # # A subsequent call to include_required_css will render... # # => # # <% require_css('style', 'ie-specific') %> # # A subsequent call to include_required_css will render... # # => # # # def require_css(*css) @required_css ||= [] @required_css |= css end # A method used in the layout of an application to create + # # # my_action.herb has a call to require_js 'jquery', 'effects', 'validation' # # File: layout/application.html.erb # include_required_js # # => # # # # # def include_required_js(options = {}) return '' if @required_js.nil? js_include_tag(*(@required_js + [options])) end # A method used in the layout of an application to create ++ tags for CSS stylesheets required in # in templates and subtemplates using require_css. # # ==== Options # bundle:: The name of the bundle the stylesheets should be combined into. # If +nil+ or +false+, the bundle is not created. If +true+, a # bundle named all.css is created. Otherwise, # :bundle is treated as an asset name. # # ==== Examples # # my_action.herb has a call to require_css 'style' # # File: layout/application.html.erb # include_required_css # # => # # # my_action.herb has a call to require_js 'style', 'ie-specific' # # File: layout/application.html.erb # include_required_css # # => # # # def include_required_css(options = {}) return '' if @required_css.nil? css_include_tag(*(@required_css + [options])) end # The js_include_tag method will create a JavaScript # +