Swap CSS

I’d like a button that will reload the current controller/action/view
but with an alternative CSS (eg, Print Version and Large Text Version).

Has anyone done this in Rails and if so are you able to provide me with
your code?

Thanks

Presumably, the easiest way to do this would be to have some session
value, or an instance variable, hold the stylesheet choice and
reference that in the layout…

<%= stylesheet_link_tag “#{session[:stylesheet]}” %>

Your button, when clicked, would simply update this session value.


Peter Wright
[email protected]

Personal Blog → http://peterwright.blogspot.com
Agile Development Blog → http://exceeding-expectations.blogspot.com

Perhaps #{params[:style]} may work better as you can link to it quite
easily.

Long

----- Original Message -----
From: “Pete W.” [email protected]
To: [email protected]
Sent: Wednesday, September 06, 2006 8:07 AM
Subject: [Rails] Re: Swap CSS

But if we’re talking about a stylesheet applied to a layout used in
all pages of the app, wouldn’t params make things a little tricky?


Peter Wright
[email protected]

Personal Blog → http://peterwright.blogspot.com
Agile Development Blog → http://exceeding-expectations.blogspot.com

But if we’re talking about a stylesheet applied to a layout used in all
pages of the app, wouldn’t params make things a little tricky?
It’d make it very tricky.

I’d say have a StylesController with a ‘switch’ method

class StylesController < ApplicationController
def switch
if params[:style]
session[:stylesheet] = params[:style]
end
end
end

Then a nice route:

map.connect ‘/style/switch/:style/’

to make urls like this:

/style/switch/print
or
/style/switch/large_text

Then in the layout:

<%= stylesheet_link_tag session[:stylesheet] || “my_default” %>

As long as you name your stylesheets print.css or large_text.css they’ll
be picked up. If nothing is specified, your default stylesheet will be
loaded.

Hope that helps,

Steve

On 9/6/06, Pete W. [email protected] wrote:

Presumably, the easiest way to do this would be to have some session value,
or an instance variable, hold the stylesheet choice and reference that in
the layout…

<%= stylesheet_link_tag “#{session[:stylesheet]}” %>

Your button, when clicked, would simply update this session value.

You could set it in a cookie too, so that the user gets his choice of
styles back automatically.

You might also want to check out the details of the media attribute for
stylesheet link tags - http://www.w3schools.com/css/css_mediatypes.asp.

A stylesheet linked with media=print will be used for printing, whether
the page is reloaded in the browser using that stylesheet or not. It’s a
nice feature - you create two stylesheets, page looks great on screen,
page looks great on paper, user doesn’t have to do anything except hit
the print button in the browser.

Not sure how to apply to your Large Text idea, but again - just and fyi
on something else you might want to look into.

c.

Xia __ wrote:

I’d like a button that will reload the current controller/action/view
but with an alternative CSS (eg, Print Version and Large Text Version).

Has anyone done this in Rails and if so are you able to provide me with
your code?

Thanks

On Sep 6, 2006, at 9:07 AM, James L. wrote:

Your button, when clicked, would simply update this session value.

You could set it in a cookie too, so that the user gets his choice of
styles back automatically.

The nice way to do this IMHO is to use alternate style sheet tags

and a little js to set a cookie. That way you can switch the
stylesheet without reloading the page. Something like this:

In the head of your layout:

The links to change the stylesheet:

Main
Print
Large Text

And the style_switch.js file:

function setActiveStyleSheet(title) {
var i, a, main;
for(i=0; (a = document.getElementsByTagName(“link”)[i]); i++) {
if(a.getAttribute(“rel”).indexOf(“style”) != -1 && a.getAttribute
(“title”)) {
a.disabled = true;
if(a.getAttribute(“title”) == title) a.disabled = false;
}
}
}

function getActiveStyleSheet() {
var i, a;
for(i=0; (a = document.getElementsByTagName(“link”)[i]); i++) {
if(a.getAttribute(“rel”).indexOf(“style”) != -1 && a.getAttribute
(“title”) && !a.disabled) return a.getAttribute(“title”);
}
return null;
}

function getPreferredStyleSheet() {
var i, a;
for(i=0; (a = document.getElementsByTagName(“link”)[i]); i++) {
if(a.getAttribute(“rel”).indexOf(“style”) != -1
&& a.getAttribute(“rel”).indexOf(“alt”) == -1
&& a.getAttribute(“title”)
) return a.getAttribute(“title”);
}
return null;
}

function createCookie(name,value,days) {
if (days) {
var date = new Date();
date.setTime(date.getTime()+(days2460601000));
var expires = “; expires=”+date.toGMTString();
}
else expires = “”;
document.cookie = name+"="+value+expires+"; path=/";
}

function readCookie(name) {
var nameEQ = name + “=”;
var ca = document.cookie.split(’;’);
for(var i=0;i < ca.length;i++) {
var c = ca[i];
while (c.charAt(0)==’ ') c = c.substring(1,c.length);
if (c.indexOf(nameEQ) == 0) return c.substring
(nameEQ.length,c.length);
}
return null;
}

window.onload = function(e) {
var cookie = readCookie(“style”);
var title = cookie ? cookie : getPreferredStyleSheet();
setActiveStyleSheet(title);
}

window.onunload = function(e) {
var title = getActiveStyleSheet();
createCookie(“style”, title, 365);
}

var cookie = readCookie(“style”);
var title = cookie ? cookie : getPreferredStyleSheet();
setActiveStyleSheet(title);

Cheers-
-Ezra

On Wed, Sep 06, 2006 at 10:06:19AM +0200, Xia __ wrote:
} I’d like a button that will reload the current controller/action/view
} but with an alternative CSS (eg, Print Version and Large Text
Version).
}
} Has anyone done this in Rails and if so are you able to provide me
with
} your code?

This is the wrong approach, both for efficiency and for the convenience
of
the user. It is preferable to serve up CSS only once and have the client
browser cache it, even if that means sending more CSS the first time.
Within reason, it is worthwhile to trade larger data sends for fewer
HTTP
connections (i.e. send more CSS at once so you don’t have to send
another
chunk later).

The way to go about this is to have all of your CSS rooted at
body.class_name and have a different class name for each style. Changing
styles can be done in JavaScript by just changing the class of the body
tag, which improves the user experience as well (no page refresh to get
a
new style).

Of course, to work with browsers that have JavaScript turned off (and to
support saving a user’s preferred style) you need to have the
class=“class_name” of the body tag in a conditional in your view, and
grab
that class_name from the params, the session, or stored user data. Your
“change style” link/button/whatever needs to do a page refresh with the
right style param unless JavaScript intervenes and just changes the body
class on the fly.

To make this clearer, I’ll give an example:

Foo .hidden { display: none; } #content { /* default theme */ background-color: #EEEEEE; color: black; width: 20em; padding: 3ex; text-align: center; } body.green_theme #content { background-color: #99FF99; color: black; } body.blue_theme #content { background-color: #9999FF; color: black; } body.christmas #content { background-color: green; color: red; }
The quick brown fox jumps over the lazy dog.
Default Green Blue Merry Christmas!

Note that the inline CSS should really be in a separate static file.
Also
note that the JavaScript depends on Prototype. There is a certain lack
of
cleanliness to this since it’s just an example, but I did test it with
Firefox.

} Thanks
–Greg

Hmm, you are right. I got a bit ahead of myself there.

The approach I would take is to add a before_filter. It would
check params for a “new” style and set the value in the session,
like you’ve suggested.

Now one can construct links to switch styles with ease.

Long

----- Original Message -----
From: “Pete W.” [email protected]
To: [email protected]
Sent: Wednesday, September 06, 2006 11:53 AM
Subject: [Rails] Re: Swap CSS

I think a smell a CSS/JS switcher plugin or at least a recipe.

Any takers?

Ezra Z. wrote:

On Sep 6, 2006, at 9:07 AM, James L. wrote:

Your button, when clicked, would simply update this session value.

You could set it in a cookie too, so that the user gets his choice of
styles back automatically.

The nice way to do this IMHO is to use alternate style sheet tags
and a little js to set a cookie. That way you can switch the
stylesheet without reloading the page. Something like this:

In the head of your layout:

The links to change the stylesheet:

Main
Print
Large Text

And the style_switch.js file:

function setActiveStyleSheet(title) {
var i, a, main;
for(i=0; (a = document.getElementsByTagName(“link”)[i]); i++) {
if(a.getAttribute(“rel”).indexOf(“style”) != -1 && a.getAttribute
(“title”)) {
a.disabled = true;
if(a.getAttribute(“title”) == title) a.disabled = false;
}
}
}

function getActiveStyleSheet() {
var i, a;
for(i=0; (a = document.getElementsByTagName(“link”)[i]); i++) {
if(a.getAttribute(“rel”).indexOf(“style”) != -1 && a.getAttribute
(“title”) && !a.disabled) return a.getAttribute(“title”);
}
return null;
}

function getPreferredStyleSheet() {
var i, a;
for(i=0; (a = document.getElementsByTagName(“link”)[i]); i++) {
if(a.getAttribute(“rel”).indexOf(“style”) != -1
&& a.getAttribute(“rel”).indexOf(“alt”) == -1
&& a.getAttribute(“title”)
) return a.getAttribute(“title”);
}
return null;
}

[snip]

Cheers-
-Ezra

I like Ezra’s basic approach to this, but I’m wondering if it can be
done in a more “Railsy way”, with less javascript and perhaps using
Ajax. Is there a way I can enable/disable the appropriate link elements
with a render :update (or a rjs file)?

I’m looking to use radio buttons for the “style selection”, and then use
an “observe_form” to watch the radio buttons and call an ajax action
that will then do the enabling/disabling of the various CSS links and
also save the new selection to the session variable.

This is all working except that I don’t know how to “get at” the link
elements in my rjs.

thanks,
jp

Bill wrote:

I think a smell a CSS/JS switcher plugin or at least a recipe.

Any takers?

I agree, sounds like a good “pay it forward” project for me. Only
problem is that I don’t know how to “get at” the css link elements from
an rjs file to enable and disable them.

So far, all of the rjs stuff I’ve done has been using element “id” or
class “id”. If somebody knows how to stuff an “id” into a CSS link,
that would probably get me moving again.

jp

Hey Good Idea!

I was thinking the conditional css route was most rails, perhaps using a
session

any thoughts?

personally i wanted an interface with two css options
some pseudo code sketch thing =>


| | | |
| Large Text | | Print Version |
|____________| |_______________|
| |
| |
V V
link_to :css[large] link_to :css[print]
return {link_to :css[normal]} return {link_to :css[normal]}