CssBrowserSelector

A plugin based on the css_browser_selector to add the browser type and os to either the body and/or html elements within a document. The full usage on how to use these css selectors can be understood at:

http://rafael.adm.br/css_browser_selector/

Major Props to Rafael Lima (from above link) who implemented this JS and has helped me with the plugin.

The initial implementation relies on javascript to place these selectors on the html element. This plugin will add these selectors to a page regardless of whether or not javascript is enabled.

CssBrowserSelector plugin provides an implementation for body and html content_tags, supplying the css_browser_selectors by default. The original javascript is also supplied and can be rendered inline if this is your preference, along with some other helper javascripts.

CssBrowswerSelector is aware of Page Caching and tracks each controller’s caches_page actions. If the page is cached, CssBrowserSelector will revert to the original javascript only version of css_browser_selector the browser and platform _will not_ be cached into the rendered html. See more in Caching, below.

Body Example

To add css_browser_selectors to your body tag in your layout (make sure you don’t output the content with <%= %> or you may end up with double content). Do the following:

<% body do %>
  <%= yield %>
<% end %>

This will render, depending on your user agent string:

<body class="gecko mac">
  <div>This is a test</div>
</body>

HTML Options

You may pass any html_options as you would expect:

<% body :onload => "alert('yo')" do %>
  <%= yield %>
<% end %>

Renders:

<body class="gecko mac" onload="alert('yo')">
  <div>This is a test</div>
</body>

HTML Example

Or, if you prefer, you can add the css_browser_selectors to your html tag as first realized in the original javascript.

<% html do %>
  <head>
    <title>Example</title>
  </head>
<body>
  <%= yield %>
</body>
<% end %>

Renders, by default, with the following attributes (which may be overriden by passing options):

<html class="gecko mac" xmlns="http://www.w3.org/1999/xhtml" xml:lang=>"en" lang=>"en">
  <head>
    <title>Example</title>
  </head>
<body>
  <div>This is a test</div>
</body>
</html>

Javascripts

You can use the plugin just to include the original css_browser_selector javascript inline:

<%= javascript_tag css_browser_selector %>

Renders, as you would expect:

<script type="text/javascript">
//<![CDATA[
var css_browser_selector = function() {
          	var
          		ua=navigator.userAgent.toLowerCase(),
          		is=function(t){ return ua.indexOf(t) != -1; },
          		h=document.getElementsByTagName('html')[0],
          		b=(!(/opera|webtv/i.test(ua))&&/msie (d)/.test(ua))?('ie ie'+RegExp.$1):is('gecko/')? 'gecko':is('opera/9')?'opera opera9':/opera (d)/.test(ua)?'opera opera'+RegExp.$1:is('konqueror')?'konqueror':is('applewebkit/')?'webkit safari':is('mozilla/')?'gecko':'',
          		os=(is('x11')||is('linux'))?' linux':is('mac')?' mac':is('win')?' win':'';
          	var c=b+os+' js';
          	h.className += h.className?' '+c:c;
          }();
//]]>
</script>

You can pass the css_browser_selector a string or symbol of the tag in which to place the selectors (‘html’ is the default):

<%= javascript_tag css_browser_selector(:body) %>

Changes this line in the script:

		h=document.getElementsByTagName('body')[0],

To add the ‘js’ selector to your element, a Page Cache aware helper to include inline javascript is available:

<%= javascript_to_add_js_to :body %>

This will put the following javascript inline:

<script type="text/javascript">
//<![CDATA[
Window.addLoadEvent = function(f){var oldf=window.onload; window.onload=(typeof window.onload!='function')?f:function(){oldf();f();}}
Window.addLoadEvent(function(){e=document.getElementsByTagName('body')[0];e.className+=e.className?' js':'js'})
//]]>
</script>

This script is included only if the action is not page cached. If the page is cached, the javascript version of css_browser_selector will add the ‘js’ selector to your element. If you want to by-pass this Page Caching awareness you can:

<%= javascript_tag window_on_load_add_js_to_tag(:body) %>

If you enjoy the Window.addLoadEvent function and wish to use it alone, as a convenience you can:

<%= javascript_tag window_add_load_event %>

Options

For those who wish to use the html and body content tags but wish to turn off the css_browser_selectors you can turn them off. For example, if you are using both helpers:

<% html :exclude_browser_and_os => true do %>
  <head>
    <title>Example</title>
  </head>
<% body do %>
  <%= yield  %>
<% end %>
<% end %>

Renders:

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang=>"en" lang=>"en">
  <head>
    <title>Example</title>
  </head>
<body class="gecko mac">
  <div>This is a test</div>
</body>
</html>

Page Caching

CssBrowserSelector keeps track of all the actions that each controller lists in caches_page in a class attribute called page_cached_actions. Each controller instance will have a method called page_cached? to determine if the action was listed in caches_page and honors the perform_caching configuration.

Currently, it does not keep track of actions cached directly through cache_page, but could be extended in the future to handle this need. Additionally, it does not track action_caching which could also be added at a later time.

Both the page_cached_action class variable and page_cached? instance method are added by the ActionController::CachingTracker module and can be accessed from anywhere you can get a reference to a controller:

CustomController.page_cached_actions #=> ["new", "show"]
controller.page_cached_actions       #=> ["new", "show"]
controller.page_cached?              #=> true if perform_caching is true and is action_name in page_cached_actions

Copyright © 2008 Los Angeles Times (www.latimes.com) released under the MIT license