Changing CSS on the fly in a UIWebView on iPhone

Posted by Shaggy Frog on Stack Overflow See other posts from Stack Overflow or by Shaggy Frog
Published on 2010-03-29T07:23:09Z Indexed on 2010/03/30 5:53 UTC
Read the original article Hit count: 746

Filed under:
|
|
|

Let's say I'm developing an iPhone app that is a catalogue of cars. The user will choose a car from a list, and I will present a detail view for the car, which will describe things like top speed. The detail view will essentially be a UIWebView that is loading an existing HTML file.

Different users will live in different parts of the world, so they will like to see the top speed for the car in whatever units are appropriate for their locale. Let's say there are two such units: SI (km/h) and conventional (mph). Let's also say the user will be able to change the display units by hitting a button on the screen; when that happens, the detail screen should switch to show the relevant units.

So far, here's what I've done to try and solve this.

The HTML might look something like this:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US" lang="en-US">
<head>
<title>Some Car</title>
<link rel="stylesheet" media="screen" type="text/css" href="persistent.css" />
<link rel="alternate stylesheet" media="screen" type="text/css" href="si.css" title="si" />
<link rel="alternate stylesheet" media="screen" type="text/css" href="conventional.css" title="conventional" />
<script type="text/javascript" src="switch.js"></script>
</head>
<body>
<h1>Some Car</h1>
<div id="si">
<h2>Top Speed: 160 km/h</h2>
</div>
<div id="conventional">
<h2>Top Speed: 100 mph</h2>
</div>
</body>

The peristent stylesheet, persistent.css:

#si
{
    display:none;
}

#conventional
{
    display:none;
}

The first alternate stylesheet, si.css:

#si
{
    display:inline;
}

#conventional
{
    display:none;
}

And the second alternate stylesheet, conventional.css:

#si
{
    display:none;
}

#conventional
{
    display:inline;
}

Based on a tutorial at A List Apart, my switch.js looks something like this:

function disableStyleSheet(title)
{
    var i, a;
    for (i = 0; (a = document.getElementsByTagName("link")[i]); i++)
    {
        if ((a.getAttribute("rel").indexOf("alt") != -1) && (a.getAttribute("title") == title))
        {
            a.disabled = true;
        }
    }
}

function enableStyleSheet(title)
{
    var i, a;
    for (i = 0; (a = document.getElementsByTagName("link")[i]); i++)
    {
        if ((a.getAttribute("rel").indexOf("alt") != -1) && (a.getAttribute("title") == title))
        {
            a.disabled = false;
        }
    }
}

function switchToSiStyleSheet()
{
    disableStyleSheet("conventional");
    enableStyleSheet("si");
}

function switchToConventionalStyleSheet()
{
    disableStyleSheet("si");
    enableStyleSheet("conventional");
}

My button action handler looks something like this:

- (void)notesButtonAction:(id)sender
{
    static BOOL isUsingSi = YES;
    if (isUsingSi)
    {
        NSString* command = [[NSString alloc] initWithString:@"switchToSiStyleSheet();"];
        [self.webView stringByEvaluatingJavaScriptFromString:command];
        [command release];
    }
    else
    {
        NSString* command = [[NSString alloc] initWithFormat:@"switchToConventionalStyleSheet();"];
        [self.webView stringByEvaluatingJavaScriptFromString:command];
        [command release];
    }
    isUsingSi = !isUsingSi;
}

Here's the first problem. The first time the button is hit, the UIWebView doesn't change. The second time it's hit, it looks like the conventional style sheet is loaded. The third time, it switches to the SI style sheet; the fourth time, back to the conventional, and so on. So, basically, only that first button press doesn't seem to do anything.

Here's the second problem. I'm not sure how to switch to the correct style sheet upon initial load of the UIWebView. I tried this:

- (void)webViewDidFinishLoad:(UIWebView *)webView
{
    NSString* command = [[NSString alloc] initWithString:@"switchToSiStyleSheet();"];
    [self.webView stringByEvaluatingJavaScriptFromString:command];
    [command release];
}

But, like the first button hit, it doesn't seem to do anything.

Can anyone help me with these two problems?

© Stack Overflow or respective owner

Related posts about iphone

Related posts about cocoa-touch