Charl van Niekerk » Blog

Main

Latest

Archives

Powered by Blogger

Anonymous Wiki Edits

As far as I can remember, all publicly editable wikis I encountered so far has anonymous edits enabled. Well, it's the default configuration in most wiki CMSs it seems! These are the things that really irritate the crap out of me!

First of all, for the, eh, "wiki uninformed", what I mean by anonymous edits are edits that are done without the user logging in first. The history/recent changes page(s) then shows an IP address instead of a username next to the edit.

So, why is this so irritating? Since an IP address can belong to virtually anyone. This gives you no indication of who (or maybe "what", who knows what might be out there?) made the edits to the page.

On a public wiki, typically anybody can register fairly easily. I feel that, if you want to make modifications to a wiki page, going through the registration procedure is not too much to ask. Also, this makes it a bit more difficult for spammers.

The problem is that many people simply forget to log on, or for some reason got logged off and accidentally made an anonymous edit. This happened a lot to me at the start, and still happens sometimes. And every time I hate myself for it, although I actually hate the system for it more.

If the wiki forced you to log in first, that would successfully solve the problem. On the better wiki systems, like Mediawiki, there's a simple configuration parameter you need to set in the config in order to force this:

$wgWhitelistEdit = true;

(You can read more here if you like.)

This solves quite a few problems, and is a general improvement in my humble opinion. Let's face it: users are stupid, or at least, they don't want to use their brains for the small things (there is already too much to worry about). And by that, I don't just mean end users, I mean all users, and I happily include myself in that class.

Computers should tell us if (well, actually "when") we're stuffing up, and they should try their best to prevent it.

The point of this post: Anonymous edits suck. They carry no advantages. If you own a publicly editable wiki, please disable them. It's easy enough (or at least, it should be, otherwise the programmers stuffed up), and you save your users (and yourself) a lot of headaches by doing so.

Expandable Menu

Updates: As Krijn pointed out to me, using javascript: in the onclick attribute is bad practice. This script is actually based on a very old script of mine, so there seems to be some crap left in it (although I thought I took most of it out). Also, Krijn pointed me to some interesting resources about JavaScript that I think is worth a read, although this still didn't make me like JavaScript (much more). :)

Since I'm about to go for a redesign, I'm just blogging about all the technology I've been using in the current template, hopefully to learn and inspire others about the basics of proper standards compliant coding.

One of the very important things to remember is that standards touch about every part of web design and development. This includes all of the following:

... and most of these items are heavily intertwined, but that another post. Although there's been much done regarding awareness of most of the items on this list, there are a few that still need some serious attention. In particular, usability and scripting.

JavaScript started at Netscape and was later also adopted by IE. Well, actually Microsoft had their own plans with their JScript anyway. Although there has been some API docs drawn up by Netscape and others, it never properly got standardised by a standards organisation (as far as I know), so it remains to be a bit deurmekaar (Afrikaans for a real mess).

The next hope is ECMAScript which is supposed to be based on several technologies, including JavaScript and JScript. I've taken a quick look at the spec, and it indeed seems very cool.

We'll have to wait a while for real ECMAScript support still, it seems. So, that leaves us with JavaScript.

The menu used on this site is actually really simple. Let's take a look at an example of the HTML source code that could be used:

<div id="nav">
 <h3>Main</h3>
 <ul>
  <li><a href="/">Home</a>
  <li><a href="/contact">Contact</a>
  <li><a href="/about>About</a>
 </ul>
 <h3>Archives</h3>
 <ul>
  <li><a href="/2005/05">May 2005</a>
  <li><a href="/2005/06">June 2005</a>
  <li><a href="/2005/07">July 2005</a>
 </ul>
 <h3>About</h3>
 <p>Some text describing something...
 <p>A waste of time, just an example...
 <p>Whatever you want, how much you want!
</div>

(Note that it's probably not a good idea to have the Home link hidden in another menu, but this is only an example.)

So here we've got a whole lot of elements all grouped together neatly within a div. We need to be able to identify this div; the easiest way is to give it an id (in this case nav).

Inside we have a couple of headings each with their respective "content" below them. The idea is that, at first, all the "content" is hidden and when you click on any heading the respective "content" for that heading gets displayed. When the user clicks on that heading again, that "content" gets hidden again.

We obviously need some way to identify what's a heading and what's not; in this case it's easy since the headings are the only h3 elements and the "content" is everything else.

Now, let's take a look at a simple JavaScript implementation that will work with the above markup.

// ----- Config -----
var wrapper = "nav";
var heading = "H3";
// ------------------

var elements = document.getElementById(wrapper).childNodes;

for(var i = 0; elements[i]; i++)
 if(elements[i].nodeName == heading)
  elements[i].setAttribute("onclick", "toggle(" + i + ")");
 else if(elements[i].nodeType == 1)
  elements[i].style.display = "none";

function toggle(i) {
 for(i++; elements[i] && elements[i].nodeName != heading; i++)
  if(elements[i].nodeType == 1)
   if(elements[i].style.display == "none")
    elements[i].style.display = "block";
   else
    elements[i].style.display = "none";
}

First I created a small config section, which is actually unnecessary but it's probably the easiest to have it separate so that one can easily change basic settings without having to dive into the script itself.

As you can see wrapper and heading are set here to the appropriate values to work with the markup shown previously. Also note that I used H3 instead of h3. This is because I'm using HTML and not XHTML; all element names in HTML are converted to uppercase in the DOM irrespective of how they are coded in the source document. In XHTML, however, being a markup language defined in XML, element names are coded case sensitive in the source document, and all elements names in XHTML are lower case. Therefore you'll have to use h3 instead.

All dumkopfen, please note: When I'm talking about using XHTML, I mean using real XHTML as sent under one of the "proper" MIME types. Don't come here and tell me you're using XHTML when you're using the text/html MIME type since then your nice little "XHTML" document will be parsed just as if it was HTML.

Having var when using a variable for the first time seems not to be necessary in the implementations I encountered so far (remember that JavaScript isn't really standardised properly, so as far as I'm concerned implementations are all one can go by). It's probably best to have them there, so I added them in, although I'm not sure about this (my JavaScript skills are probably not what they should be, but to get skills up to scratch in a kak language like JavaScript is not one of my highest priorities at the moment).

Also note that I said "when using a variable for the first time" instead of "declaring a variable" since "declare" just seems too good and proper for JavaScript. Ok, now I'm just being nasty... ;)

Moving on, this implementation is completely modular. You don't have to hard-code all kinds of attributes like onclick and myriads of ids here, everything is handled by the script automatically based on the placement of the various elements in the DOM.

Now note the first loop. This runs through all the child nodes of the master div (let's call it that - note the correct use of the dfn element there). We assign each heading an onclick attribute to call the toggle function. Also note that we actually tell it where it's located in the DOM so that the function knows from where to continue. This could be made much more elegant by using DOM 3 Events (see this post), but for now let's just keep it basic. More tutorials on improvements of this script will follow.

All other elements (those that aren't headings in other words) are simply hidden for now. (This will happen when the script if loaded, after all.)

Now the toggle function: This will start right after the heading (the heading's position is given, remember) and continue until it finds the next heading, making everything in between either visible or hidden.

My technique here is to check if it's visible and then make it hidden, and vice versa. This is the easiest, but not the most reliable technique, since if you actually use CSS etc. to hide some of those elements this will prettymuch stuff it all up. There are more complex solutions you could go for which might solve that problem, but I'm not going to go into that now. For now, we'll assume you're trying to build a simple, straight-forward menu here without any funnybusiness. ;)

Also note my constant checking to see if the node is of type 1. Why am I doing this? Because node type 1 is an element. Everybody that ever really got down and dirty with the DOM will be able to tell you that text nodes are also, well, nodes. There are some other types of nodes too I thought, but anyway, trying not to go off track here...

You might say "Yeah, but in your example all children of the master div are elements." Indeed, but what about the whitespace? ;)

The point is that you normally shouldn't just assume a node is going to be an element. First check. If necessary, check again (just kidding...) otherwise your JavaScript might be producing errors. And never underestimate that whitespace... it's one of the most common mistakes beginners make (so if you're a beginner, don't feel bad).

I think I explained most of what is going on here, but don't be afraid to ask. (As always, well, almost always, on this blog, comments are open.) :)

Just as a closing note, this script works in both Firefox & Opera. I just label it as application/x-javascript which makes IE do nothing with it, making it perfectly backwards compatible. Also, when JavaScript disabled, everything works perfectly. That's what I call responsible use of client-side scripting!

charlvn.za.net

Screenshot

Ok, after a few years I finally got around to finishing this site. Charlvn.za.net is now live!

The purpose of this site is to be my "home base" and something for me to link my name to when commenting, in profiles, signatures, etc. Although the content isn't entirely finished yet, that site will soon have links to all my other sites, blogs, etc.

I decided to stick to a minimal and clean design. Green, being my favourite colour, is used liberally (maybe even too much).

At first, the logo was embedded in the markup and linked to the homepage. Although it feels more natural to me that way, I later decided to put it into the CSS.

Many sites have the convention of linking the logo to the homepage. It is normally best to follow conventions, but this convention happens to break a basic usability rule: Everything needs to be visible and preferably fairly obvious to the user. Personally, I prefer to have a link to the homepage as the first item of the main navigation.

Since linking the logo is a convention, it's probably best to have a link to the homepage from both the logo and the main navigation, but this bothers me too in a way. Now you actually have two links to the homepage directly following each other. This felt to me a bit unnatural, especially when taking screen readers into account. Of course this problem could easily be fixed for aural user agents when they support aural stylesheets, but afaik they don't at the moment.

Anyway, I'm going to leave that as it is for now but I might change it into the future.

This site is full of HTML instead of XHTML, simply because I didn't need the "X" and search engine listings are an added advantage in this case. I don't feel completely happy about my decision, but since content negotiation is basically a waste of time I think I'm going to leave it like this for now. And of course sending XHTML as text/html is just out of the question. I most likely will add the "X" somewhere into the future though when support is better.

This is the first site I create in a while that's completely multi-lingual. The entire site is available in both Afrikaans and English. It actually started out as Afrikaans but then later included English as well for those that don't speak the language very diliciously (non-South Africans will probably not catch that joke, don't bother if you didn't).

Although I think content negotiation based on file type sucks more often than not, I think negotiation based on language is very cool. I love getting my preferred language all around the 'net automatically based on my browser settings.

I could (and probably should) have written my own custom script for this, but since I was feeling a bit lazy I thought I might give Apache Multiviews a try.

The setup was pretty straight-forward. My entire .htaccess file at the moment looks like this:

Options +Multiviews +Includes
AddHandler server-parsed .html
DirectoryIndex index
AddDefaultCharset UTF-8
AddLanguage af .af
AddLanguage en .en

First I needed to enable the multiviews and then I just needed to start mapping languages to extensions. In this case it was very easy - just needed to add af for Afrikaans and en for English. Just remember to change the DirectoryIndex though to include something without a file extension, otherwise the negotiation won't work for the default pages.

As you can also see from the above, all HTML and CSS content on my site is UTF-8 and I'm using Apache SSI to import the navigation at the top of my site. Also note that .shtml is evil. But back to multiviews.

One thing I'm quite impressed to see is how well my HTTP response headers look in this pretty static site of mine. Apache seems to handle these things very nicely. Content-language is correctly set and Content-location as well as Vary are correctly set where appropriate.

I'm still not completely happy with my URIs, but that will require some serious scripting which I'll be explaining in another post.

IE support is, needless to say, non-existant. Although they actually will now get an unstyled page instead of a download box. ;)

In Firefox things are looking great; there are one or two minor outstanding issues with Opera, but I'll be debugging all the small things as time goes on. I just need to get this site out now, since there's another project I need to finish up asap.

Creating rounded corners, Charl-style!

Two things you should know before we start:

  1. I hate excessive div and span elements.
  2. border-radius and -moz-border-radius is not to be relied upon (yet), especially when there's a background-image applied to the same element.

Because of the first point, this is all we have to work with:

<h1>Charl van Niekerk's Blog</h1>

There's actually a span around Charl van Niekerk for accessibility reasons but since we want to keep things simple I left that out in the above.

Ok, so let's get our hands dirty with the CSS. For now, we forget about the rounded corners and start styling the rest:

h1 {
 margin: 50px 20px 0 20px;
 padding: 0 0 0 20px;
 font: bold 25px/25px verdana, arial, sans-serif;
 color: white;
 background: #23508e url(http://photos17.flickr.com/20867036_0223c8ff1e_m.jpg) bottom repeat-x;
}

You might spot 25px/25px and freak, but that's your problem then. It's not really what we want (one of the reasons I'll be dumping this template soon), but we kind-of need it for this tight layout (not like it will help anyway in a browser that ignores the px bit when it resizes text - take Firefox for example), but let's just forget about this for now. 25px is large enough for most people anyway.

Now we've got a pretty straight-forward square background. Now this is where the fun begins.

Firstly you create two slices, one for the left side and one for the right side. The height of these slices must be fixed, therefore the px-based font above. Anyway, now we use the ::before and ::after pseudo-selectors to do the rest. I'm first going to paste the CSS here and then explain it all.

h1::before {
 display: block;
 margin: 0 0 -80px -20px;
 height: 97px;
 content: "";
 background: transparent url(http://photos15.flickr.com/20867037_0bf39086ca_m.jpg) left no-repeat;
}

This is obviously for the left side. We use display:block since we need to use negative margins etc., and we set the height to the exact height of this slice. We must make content something, otherwise this won't do anything. Since we don't really want to display any text there, we just make it blank. Then we set the background to the slice, otherwise this exercise will be pretty pointless, yes?

On the h1 element, as shown earlier, we use a left padding of 20px to get the text positioned correctly. In order to place this element completely on the left side, we therefore need to use a negative left margin. We also use a negative bottom margin, otherwise the text will get positioned below this (it is now block-level after all).

Ok, that's it for the left side. Now the right side:

h1::after {
 display: block;
 margin-top: -42px;
 height: 97px;
 content: "";
 background: transparent url(http://photos17.flickr.com/20867038_cc33bebe73_m.jpg) right no-repeat;
}

This looks very similar to the previous one. We now need to have a negative top margin, because otherwise this will be placed underneath the text instead of to the right of it. We don't need to worry about a right margin since the h1 element has no right padding.

Also note the right no-repeat here and the left no-repeat for the previous slice. We essentially have three overlapping "elements" here - one real element and two pseudo-elements. Therefore be careful how you align your background or else you'll stuff up.

Ok, this is a very, very simple example. There are much more complex things you can do, but the point of this article is to demonstrate that flexible formatting with CSS is indeed very possible without having this ridiculous bloat:

<div id="header-wrapper">
 <div id="header">
  <div id="main-heading">
   <h1>...</h1>
  </div>
 </div>
</div>

One of the major reasons for using CSS is that it makes your web development lifestyle so much simpler and faster while creating an efficient product and retaining accessibility; however, if you don't start to use "smart" CSS some time or the other you'll never enjoy most of these benefits. Otherwise you'll keep yourself in the dark ages of having presentation heavily influence content.

Sometimes you'll still have to compromise either the one way or the other, but if you work smartly you can create great designs while leaving your markup intact.

And if necessary, yes, (you've been waiting for this, haven't you?) Dump it!

What? South African Software Patents???

South African LUG mailing lists are going crazy about a patent that has been passed by Microsoft. Apparently the patent is titled "Word processing document stored in a single XML file that may be manipulated by applications that understand XML". This is, needless to say, totally ridiculous and wrong in so many ways it's just too bad to be true.

This effectively makes Open Office illegal. Yep.

Software patents aren't supposed to exist in South Africa, but obviously they do.

Read more:

Apparently there are some plans for putting up a local anti-software patents website. I fully support all of these causes and am willing to protest, mail, sign petitions or do anything else necessary to help stop this.

South Africa is supposed to be a democracy. This is worse than communism!

Copyright © 2004-2008 Charl van Niekerk. All articles are released under the Creative Commons Attribution 2.5 South Africa licence, unless where otherwise stated.