CSS: CSS Browser Selector

Posted over 7 years back at Revolution On Rails


Each browser has its quirks. Having a clear way of organizing the work arounds
for those quirks is a challenge. Using CSS selectors is not a new idea, but I thought it might be helpful to others to give an example of the technique and how we've been able to successfully deploy it for revolutionhealth.com.



First, for IE (the browser that usually requires a hack), we can rely on conditional comments. This is good because it means we don't need to depend on Javascript. For other browsers we'll have to rely on a document.write solution. For Safari, Opera, and Firefox, we rely on the script from http://rafael.adm.br/css_browser_selector/ and for IE, conditional comments.


Here's what we include at the top of our document. (The browser_detect_start partial.)



<!--[if lt IE 7.]>
<div class='ie ie6'>
<![endif]-->
<!--[if IE 7]>
<div class='ie ie7'>
<![endif]-->
<script type="text/javascript">//<![CDATA[
var d = browserCSSDetection();
if( d.browser != "ie" ){ document.write( "<div class='" + d.browser + " " + d.os + "'>" ); }
//]]></script>

And here's what we do for the end of the document. (The browser_detect_end partial.)

<!--[if IE ]>
</div>
<![endif]-->
<script type="text/javascript">//<![CDATA[
var d = browserCSSDetection();
if( d.browser != "ie" ){ document.write( "</div>" ); }
//]]></script>


The browser detection in Javascript. This could be enhanced further, but for us this allowed us to get the site working relatively easy in Konqueror. As well it enabled us to fix our menu's so that they float over flash in Linux using this techinque.



function browserCSSDetection()
{
// see: http://rafael.adm.br/css_browser_selector/
var ua = navigator.userAgent.toLowerCase();
var is = function(t){ return ua.indexOf(t) != -1; };
var 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':'';
// see: http://www.mozilla.org/docs/web-developer/sniffer/browser_type.html
var os = (is('x11')||is('linux'))?' linux':is('mac')?' mac':is('win')?' win':'';
var css = {browser:b,os:os};
return css;
}


Finally, to make all this fit nicely into a layout:

<head>
<%= javascript_include_tag 'browser_detect' %>
</head>
<body>
<%= render :partial => "browser_detect_start" %>
<%= @content_for_layout %>
<%= render :partial => "browser_detect_end" %>
</body>


Update:
Here's a simple example of what this enables. The advantage of this over a conditionally included file is it keeps everything about the login box isolated to one place. You don't need to worry about openning up a separate file to make your IE fixes. We do use iefix specific CSS for our site, but only for very large features like menus



#login {
padding:0px;
}
.ie6 #login {
padding: 2px;
}

Plugems - Why views in plugems?

Posted over 7 years back at Revolution On Rails


When we started to develop Plugems we had multiple applications that all shared a similar look and feel. One concept that emerged recently for me was that layouts can act like objects. In our suite of applications, we have a base layout that each application can derive from to satisfy it's unique set of presentation requirements. For example our UI plugem has the following:



ui/views/layouts/default.rhtml

Using a little magic from fora.pragprog we can extend our default layout writing the following:

<% inside_layout 'default' do -%>
<%= @content_for_layout %>
<% end -%>



As well as with layouts, there are also smaller blocks of UI that make up a page that can be shared. I've always thought of these as widgets, which in many cases can be defined as a set of partials and helpers. An application may place a widget on a view, feeding it the data needed to bring it to life. This is different from components because there is no controller logic. Really the presentation side of a widget can be expressed by a set of partials, Javascript, CSS and a healthy dose of ruby [e.g. helpers]. In this way partials are the basic building block on which many UI components can be built. By themselves they are incomplete, but within the context of an application they are alive...




Plugems enables you to share common UI widgets across multiple applications. Common assets (css, js, images) can live in a plugem, but be shared across applications at deployment time. I hope to post more in depth on this topic in near future.

Plugems - Why views in plugems?

Posted over 7 years back at Revolution On Rails


When we started to develop Plugems we had multiple applications that all shared a similar look and feel. One concept that emerged recently for me was that layouts can act like objects. In our suite of applications, we have a base layout that each application can derive from to satisfy it's unique set of presentation requirements. For example our UI plugem has the following:



ui/views/layouts/default.rhtml

Using a little magic from fora.pragprog we can extend our default layout writing the following:

<% inside_layout 'default' do -%>
<%= @content_for_layout %>
<% end -%>



As well as with layouts, there are also smaller blocks of UI that make up a page that can be shared. I've always thought of these as widgets, which in many cases can be defined as a set of partials and helpers. An application may place a widget on a view, feeding it the data needed to bring it to life. This is different from components because there is no controller logic. Really the presentation side of a widget can be expressed by a set of partials, Javascript, CSS and a healthy dose of ruby [e.g. helpers]. In this way partials are the basic building block on which many UI components can be built. By themselves they are incomplete, but within the context of an application they are alive...




Plugems enables you to share common UI widgets across multiple applications. Common assets (css, js, images) can live in a plugem, but be shared across applications at deployment time. I hope to post more in depth on this topic in near future.

Episode 26: Hackers Love Mass Assignment

Posted over 7 years back at Railscasts

Your site may be at risk! When using mass assignment, you are giving the user complete control over that model and its associations. See how a hacker might use this vulnerability and learn how to stop it in this episode.

Plugems, Welcome!

Posted over 7 years back at Rails Engines News

Revolution on Rails have finally released their solution to shared dependencies between Rails applications, which they have called Plugems (see what they’ve done there?). In their announcement they discuss some of the differences between plugins, “engines” (ahem!) and Plugems, and I think they’ve raised some interesting points.

Continue Reading…

Breaking change, and the ups and downs of FileMerge

Posted over 7 years back at The Hobo Blog

I forgot to mention – there’s a small breaking change in 0.5.3, object_table@skip_fields has been renamed to just skip (that’s the skip_fields attribute of <object_table> using a syntax that just popped into my head). The reason being that you can now use that attribute to skip both fields and associations.

I blame FileMerge - it neglected to remind me about the change. If you’re a Mac user and you’ve not discovered FileMerge (I didn’t know about it for a good while), you’re missing out. Once you’ve installed Xcode you’ll find it in /Developer/Applications/Utilities. It’s a diff/merge tool for both files and whole directory trees and, in a very Mac-like way, it just works. It’s got the most readable display of any such tool I’ve used.

You can also launch it from the command line, where it goes by the name (somewhat strangely) of opendiff.

So I just do something like

opendiff rel_0.5.2 rel_0.5.3

And document all the changes I see in the changelog.

So why was I not reminded of that breaking change? Well, one of the “just work” features of FileMerge is that it automatically ignores .svn directories – very nice. A quick look in preferences shows that there’s a pre-configured list of filename patterns the tool will ignore. And alas, in that list is “tags” (I believe that’s a ctags thing). Sometimes “just works” just doesn’t :-(.

I’ve removed ‘tags’ from that list now of course, but I’ve probably missed changes within Hobo’s tags directory in several chapters of the changelog. I should go back and fix that I guess. Hmm… :-)

And finally, absolutely free of charge, here’s a groovy FileMerge link for you :-)

Breaking change, and the ups and downs of FileMerge

Posted over 7 years back at The Hobo Blog

I forgot to mention – there’s a small breaking change in 0.5.3, object_table@skip_fields has been renamed to just skip (that’s the skip_fields attribute of <object_table> using a syntax that just popped into my head). The reason being that you can now use that attribute to skip both fields and associations.

I blame FileMerge - it neglected to remind me about the change. If you’re a Mac user and you’ve not discovered FileMerge (I didn’t know about it for a good while), you’re missing out. Once you’ve installed Xcode you’ll find it in /Developer/Applications/Utilities. It’s a diff/merge tool for both files and whole directory trees and, in a very Mac-like way, it just works. It’s got the most readable display of any such tool I’ve used.

You can also launch it from the command line, where it goes by the name (somewhat strangely) of opendiff.

So I just do something like

opendiff rel_0.5.2 rel_0.5.3

And document all the changes I see in the changelog.

So why was I not reminded of that breaking change? Well, one of the “just work” features of FileMerge is that it automatically ignores .svn directories – very nice. A quick look in preferences shows that there’s a pre-configured list of filename patterns the tool will ignore. And alas, in that list is “tags” (I believe that’s a ctags thing). Sometimes “just works” just doesn’t :-(.

I’ve removed ‘tags’ from that list now of course, but I’ve probably missed changes within Hobo’s tags directory in several chapters of the changelog. I should go back and fix that I guess. Hmm… :-)

And finally, absolutely free of charge, here’s a groovy FileMerge link for you :-)

Hobo 0.5.3 - dev mode gets a big speed boost

Posted over 7 years back at The Hobo Blog

A quick release this time – not too many changes. The reason is, I wanted to quickly get a couple of important changes to you.

The first is a fix to a trivial but annoying bug that sneaked into 0.5.2. The <show> tag was playing up so that certain “magic-updates” after in-place-edits were not working, and worse, belongs_to and has_many associations were not displayed at all by <show>. People were hitting this as soon as they tried the screencast for themselves. Not good.

The second thing is more fun. Development mode just got a whole lot faster. Like Rails, in development mode DRYML reloads every taglib on every request. Because of dependencies, we even reload taglibs that haven’t changed. Avoiding these reloads is actually pretty hard, but we’ve at least made the reload much faster by caching the generated ERB source.

This improvement was implemented by James – the new guy at HoboTech, so many thanks to James.

There’s a couple of smaller changes too, including stuff that you kind folk have reported in the forums. Check the changelog for details.

* Change Log * hobo-0.5.3.gem

Hobo 0.5.3 - dev mode gets a big speed boost

Posted over 7 years back at The Hobo Blog

A quick release this time – not too many changes. The reason is, I wanted to quickly get a couple of important changes to you.

The first is a fix to a trivial but annoying bug that sneaked into 0.5.2. The <show> tag was playing up so that certain “magic-updates” after in-place-edits were not working, and worse, belongs_to and has_many associations were not displayed at all by <show>. People were hitting this as soon as they tried the screencast for themselves. Not good.

The second thing is more fun. Development mode just got a whole lot faster. Like Rails, in development mode DRYML reloads every taglib on every request. Because of dependencies, we even reload taglibs that haven’t changed. Avoiding these reloads is actually pretty hard, but we’ve at least made the reload much faster by caching the generated ERB source.

This improvement was implemented by James – the new guy at HoboTech, so many thanks to James.

There’s a couple of smaller changes too, including stuff that you kind folk have reported in the forums. Check the changelog for details.

* Change Log * hobo-0.5.3.gem

Episode 25: SQL Injection

Posted over 7 years back at Railscasts

One of the most common security problems for dynamic sites is SQL Injection. Thankfully Rails does everything it can in solving this issue, but you still need to be aware of it.

Optimal Ad Follow-Up

Posted over 7 years back at PJ Hyett

It’s time to put my money where my mouth is based upon what I wrote a month ago regarding optimal ad placement.

The first thing I should mention is I’ve actually reduced the amount of ads since then. There are now only two posts that contain ads. They account for 85% of all incoming traffic, so I see no reason to bother visitors looking at any of my other posts.

Furthermore, I originally had placed two large ads at the top, but I’ve cut it down to just one and floated it to the left. The net effect of these changes is fewer page impressions, but no loss in revenue.

Observant viewers may have also noticed that I’ve added Kontera links to those two posts as well, which has been good for another $15 this month on top of my Adsense revenue.

12,781 pages divided by 27 days is around 473 page impressions per day. Perfect for paying for hosting, but tack on a couple of zeros to that number and suddenly you might just be able to quit your day job based upon how well you can monetize the traffic.

As a forewarning, I’ve been researching and experimenting with all things Adsense, Adwords, and Domaining, so you may see more posts of this nature. If you just want to read about Ruby and Rails, head over to Err the Blog.

More docs

Posted over 7 years back at The Hobo Blog

p.s. As I mentioned a while back, the manual source is in Markdown, and the PDF manual is generated by Safari from HTML + CSS. Anyone got any bright ideas for getting a contents page with page numbers on it?

More docs

Posted over 7 years back at The Hobo Blog

p.s. As I mentioned a while back, the manual source is in Markdown, and the PDF manual is generated by Safari from HTML + CSS. Anyone got any bright ideas for getting a contents page with page numbers on it?

Episode 24: The Stack Trace

Posted over 7 years back at Railscasts

The stack trace can be a very useful tool when it comes to debugging. Learn the ins and outs of how the stack trace works in this episode. Note: I am using an older version of the Rails bundle here so it might be a little different than yours. The command in the newer version is called Install Plugin and requires you to type textmate_footnotes in the search.

MyConfPlan: Check Me Out

Posted over 7 years back at zerosum dirt(nap) - Home

Dr Nic Williams wrote a nice little app to allow folks to plot out the sessions they’ll be attending at Railsconf (or any conference, for that matter) and share them with others. In case you’re curious, check out my tentative session list.

Some of those decisions are tough ones! In particular, I’d like to see both Nutter’s JRuby talk as well as Dan Webb’s javascript-fu presentation. I’d also like to attend both Matthew Bass’ homesteading talk as well as Brian Leonard’s Tooling/NetBeans session. Sigh, decisions decisions.

Also of note: Dr Nic built MyConfPlan in Hobo, which seems to have come a long way since I last checked it out. Very cool stuff.