June 2004

Kimmo Alm (which is Indian for The One Who Cannot Decide On Things) has finally decided to put his site online. And about damn time, too! It's not that content-rich yet, but he has a great foundation for great stuff. Also, you're able to comment on every single page on his site! He's got some random quotes in the header, and guess what? He's quoted me, Of All People. :-) Keep clicking F5 if you don't get it the first time. The only thing I can complain about is his small font size.

All in all, very nicely done, Kimmo. I'm looking forward to seeing your site grow into something big and amazing.

PS: My site no longer says "Håvard's Homepage", but rather "Håvard's web site". Kimmo thinks it sounds more professional. ^_^

I'm learning Python, and it's great fun. This is my first programming language ever, so everything's kind of fun, even the more trivial things, like traversing a string and reversing the characters. Which is what I want to talk about. Here's my code:

a = raw_input("String? ")
n = len(a)

if n == 1:
    print "Your string is", n, "character long."
else:
    print "Your string is", n, "characters long."

while n > 0:
    print a[n-1],
    n = n-1

This program asks for an input and checks the length of it. If the length is 1, it prints the singular form of "character" (along with the rest, of course). If it's not 1, it prints the plural form. It then proceeds to print the n-minus-1-th character in n (which is our string) and subtracts 1 from n every time through the while loop. The comma at the end of the print statement suppresses the line break, but it still adds a space between all the characters, which is annoying. Thankfully, Michael helped me out:

a = raw_input("String? ")
n = len(a)
i = ""

if n == 1:
    print "Your string is", n, "character long."
else:
    print "Your string is", n, "characters long."

while n > 0:
    i = i+a[n-1]
    n = n-1
print i

This does almost the same thing, except it uses concatenation, which eliminates the spaces between the characters, and waits until the end to print the reversed string. Thanks Michael. :-)

"...quemadmodum gladius neminem occidit, occidentis telum est." [...a sword never kills anybody; it's a tool in the killer's hand.]

- (Lucius Annaeus) Seneca "the Younger" (ca. 4 BC-65 AD)

Browsers, mod_rewrite, SSI, XHTML, MathML, UTF-8 and ISO-8859-1 all continue to conspire against me, ensuring that my life is as hard as possible.

Once upon a time (today in fact), Firefox started complaining about what I thought was <?xml version="1.0" encoding="ISO-8859-1"?>. I tried using that XML processing instruction because Firefox apparently doesn't fetch the AddCharset directive sent from my .htaccess file, and assumed UTF-8 as the default character encoding. This was when the moaning started. I had no idea why it started moaning, but apparently it doesn't like white-space before either a DTD or an XML processing instruction. Fine, I can accept that. Then, upon some pondering, I realized that I needed to put my SSI directive <!--#include --> before all my variables so that the white-space would disappear. The white-space disappeared, Firefox doesn't complain, and it gets ISO-8859-1 like it should. However, since the variables aren't passed to the included files, you'll see "Håvard's Homepage - (none)", followed by "(none)". I've decided that you're going to have to live with that until I collect enough courage to switch to PHP.

I amaze myself sometimes... Problem fixed. It's as simple as to just add the XML processing instruction at the very top of every page, instead of only in the included one.

I feel like debunking two myths that roam around the two IRC channels I hang around in (#html on irc.homelien.no and #web on irc.freenode.net), namely...

  1. ...that <table> was never meant endorsed by a spec to lay out web pages, and...
  2. ...that XHTML MUST NOT be sent as text/html.

A lot of people will scream these things at you, but apparently they haven't read the relevant specs thoroughly enough. I quote the HTML 3.2 table section:

"HTML 3.2 includes a widely deployed subset of the specification given in RFC 1942 and can be used to markup tabular material or for layout purposes. Note that the latter role typically causes problems when rend[er]ing to speech or to text only user agents."

Source: www.w3.org/TR/REC-html32#table

Now, of course you shouldn't misuse <table> for layout purposes, but claiming that they were never intended to do layout is a lie.

And then we have the people who claim that XHTML MUST NOT be sent as text/html. Debunking that myth is also just a matter of referring to the relevant spec. The summary clearly states that XHTML SHOULD NOT be sent as text/html, and SHOULD NOT is clearly defined in RFC2119 (there's probably an RFC on how to properly sort your laundry) as:

"This phrase, or the phrase 'NOT RECOMMENDED' mean that there may exist valid reasons in particular circumstances when the particular behavior is acceptable or even useful, but the full implications should be understood and the case carefully weighed before implementing any behavior described with this label."

Source: www.faqs.org/rfcs/rfc2119.html

I'd say that Internet Explorer not being able to even display XHTML sent with the proper MIME type is a valid reason for implementing aforementioned behavior. At least, that's my reason.

Next time you want to complain about something, do your homework.

"We don't support the browser you are currently using.

We recommend you use Netscape 6 or Internet Explorer to shop our site. If you wish to install the latest version of Netscape or Internet Explorer on your computer, please click on the links listed below."

Source: Grocery Gateway

Ha ha ha HA!

"Thank you for visiting PPP lifetime care's site. We recommend you view the site using Microsoft Internet Explorer version 4 or later.

Please click the following link to download the latest version of Microsoft Internet Explorer."

Source: Lifetime Care

Never.

"The browser you are using (Opera/7.51 (Windows NT 5.1; U) [en]) is currently unsupported. Please update your browser to the most current level."

Source: Stanton Magnetics

Update? Are you insane? As of the time of this writing, I own the absolute latest version of Opera, which is 7.51.

"The Ballard Designs Web site has detected that your browser is incompatible with our site. Please use either Microsoft Internet Explorer or Netscape Navigator version 4.0 or higher."

Source: Ballard Design

No.

"Sorry, this page does not support your browser. Please click here to upgrade to the latest version of Netscape."

Source: siig

Ok, I think that's enough.

Added outlines to pages which require them. Hopefully this will turn out to be a helpful navigation feature.

Made a CSS counters test page, and linked to it on the CSS Alacrity page. Counters are actually pretty hard to understand (well, if you read the spec and expect it to be a tutorial), but I finally managed, so I'll try to explain how I did the CSS counters test page in simpler terms than how the spec explains counters. Note that as of right now, counters are only supported by Opera (as far as I know; feel free to correct me).

A counter is created as soon as it is referred to, and is included in the content property, in either :before or :after pseudo-elements (CSS3 will allow you to use content with any selector, not limited to :before or :after). The function for counters is counter() and like everything in the content property (be it a string, the attr() function, url()...) it is concatenated with the rest with a space. counter() takes an identifier (and optionally any value from list-style-type, separated with a comma) as its argument. Put another way, you name your counters as you see fit. So, first we'll want to generated the string "Chapter " followed by the chapter number followed by the string ": " before an <h1> element:

h1:before {
  content: "Chapter " counter(chapter) ": ";
}

Actually, this won't do much good; the only thing it'll do is prefix "Chapter 0: " to every <h1> element. We want to increment it by 1 every time another <h1> is encountered. This is done with the counter-increment property. This property takes an identifier plus an optional integer as its value (or even several of the two). The integer specifies how much the counter is incremented each time the element is encountered, and can even be negative. The default value is 1 however, which fits our need just fine, so we can omit the integer in this case. Our CSS now looks like this:

h1:before {
  content: "Chapter " counter(chapter) ": ";
  counter-increment: chapter;
}

Note that the counter is incremented before it's prefixed to <h1>, even though content appears before counter-increment in the source.

That takes care of our most important headings. Now we want to prefix our <h2>s with "Section " followed by the current state of the chapter counter, followed by a dot, followed by a new counter we'll create called counter(section). Remember that counter(chapter) isn't incremented by anything else than <h1>, so it'll stay the same throughout all <h2>s until they're interrupted by another <h1>:

h2:before {
  content: "Section " counter(chapter) "." counter(section) ": ";
  counter-increment: section;
}

Uh-oh! What happens to the <h2>s interrupted by an <h1>? You're absolutely right; they'll just keep counting, which is not quite what we want. The counter-reset property will take care of that little problem. It has the exact same syntax as counter-increment, except that the optional integer specifies to what value the counter is set when being reset (the default is 0, which is what we want, so we omit the integer once again). So for every <h1> encountered, we want counter(section) reset. Here's the first CSS rule, modified:

h1:before {
  content: "Chapter " counter(chapter) ": ";
  counter-increment: chapter;
  counter-reset: section;
}

This means that we must also reset the counter for our <h3> elements (which we'll call counter(sub-section)) whenever an <h2> element is encountered. Our second CSS rule is thusly modified:

h2:before {
  content: "Section " counter(chapter) "." counter(section) ": ";
  counter-increment: section;
  counter-reset: sub-section;
}

So as you can see, counters are pretty nifty. Realize that counter-increment doesn't need to be in the same rule block as the counter() it increments. This allows for cool effects, such as, say, counting the number of paragraphs on a page and displaying the results at the bottom of the page. (Though a silly idea, it's a good way to understand counters.) Create a dummy <div> at the bottom of the page, called, say, <div id="para_counter">. CSS is as follows:

p {
  counter-increment: paragraphs;
}

div#para_counter:before {
  content: "There are " counter(paragraphs) " paragraphs on this page.";
}

Incidentally, I now use counters to count the number of quotes I have on the Quotes page.

There are 12 posts for June 2004.