Make it go away
More and more, I avoid using scripting on web pages. Some sites use very complex scripting, for example to make the menus mimic the operation of the standard GUI menus as found in MacOS and Windows. The problem arises when the user comes along with a browser the web designer hasn’t considered: not only may the menus not work at all, the browser may crash. That’s quite a lot of irritation for a user just because you want a flashy menu.
But sometimes a bit of simple JavaScript can be just what you want. One case recently came up in the writing of my Weblog page. I had a quote or two from Le Monde: I wanted the original there so that anyone who could read French would not be reliant on my possibly imperfect translation; I wanted to provide a translation because the online translation services can produce quite bizarre results. The ideal solution, it seemed to me, would be to have the original there and the translation only present should the user want it.
Thinking of this sort of problem probably first brings to most people’s minds the notion of having an invisible <div> positioned under the original, with a link which would invoke a script making the translation visible and bring it to the front to overlie the original. If the page were static, that’s probably not a bad solution — but for a page which is updated very regularly, and where the existing text is moved down as new content is added, it is not going to be simple to implement.
Another approach would be to use a pop-up — except that there is widespread loathing of pop-up windows (and no wonder, since they slow down page loading and can crash some browsers). Using a link to a separate page, whether targetted at a pop-up window or the current window, also has the disadvantage of requiring a server access, meaning a delay before the translation appears.
No, the ideal approach for most users would be the <div> which can be made visible or invisible as desired. Since the position would vary as the document was updated, I wouldn’t specify a position. I used CSS like this for the basic definition of the <div>, identifying it by ID:
#thediv {
border: 1px dotted #000066;
background-color: #ffffee;
color: #000033;
}
There’s nothing there which will affect the visibility of the element. The first thought is probably to use the visibility property, setting it as "hidden" initially and using a link to make the relevant content visible. A routine such as that given in the article on manipulating page elements in Netscape 6 might be used. There is a problem, though, as you can see by using this link.
This paragraph was hidden (for most users of graphical browsers) before that link was clicked. But you will have noticed that there was a blank space there even before the paragraph was revealed. The paragraph may not be visible, but it still occupies part of the page. This is not a particularly elegant solution! (If you didn’t notice this, use this link to hide the paragraph again.)
As I say, not an elegant solution. What we want is something which will hide the paragraph and allow the content beneath to close up as though the hidden paragraph were not there at all. Fortunately, there is a property which will allow us to do just that. (You can bring it back if you want.) There is, though, one big caveat which we’ll come to later.
The key to this is the display property. The visibility property determines whether or not an element is visible (obviously) but the element, as we’ve seen, is still there; the display property determines if an element will be displayed at all, and, if it is, how it will be displayed. There are four possible values for this property: block, inline, list-item and none. If the value is none, then the display of the element in question will be “turned off” and the rest of the page content will close up and be rendered as though that element were not in the markup at all. For example, using this in your stylesheet would turn off all the images on your page:
img {
display: none;
}
The other values are pretty self explanatory: a value of block puts the element in a “box” positioned relative to other elements, i.e. it will be separated by white space from other block elements; inline puts the box on the same line as the previous content. A value of list-item is the same as block except that a list-item marker is added to the element.
The way I implemented it was very simply to put the translation in a <div> defined using the CSS I showed earlier. That CSS went in the main style sheet. In the <style> element in the page’s head I added a rule for the element ID:
<style>
@import url(mainstylesheet.css);
#thediv {
display: none;
}
<style>
I put it there because not all browsers will acknowledge the display: none; rule if it is included in the main stylesheet with the other rules for that element.
Next in the head of the document I put a JavaScript function which is in some ways similar to the one shown in the article about DHTML and Netscape 6:
<script language="JavaScript1.2" type="text/JavaScript">
function varyDisplay(ident,vStr) {
var changeStr;
var theObj;
var dispStr;
if (document.getElementById) {
changeStr = "document.getElementById('" + ident + "')";
theObj = eval(changeStr);
if (theObj) {
theObj.style.display = vStr;
}
} else if (document.all) {
changeStr = "document.all['" + ident + "']";
theObj = eval(changeStr);
if (theObj) {
theObj.style.display = vStr;
}
}
}
</script>
Assuming the <div> containing the translation has an ID defined as "thediv", it would be revealed by a link like so:
<a href="javascript:varyDisplay('thediv','block')>in English</a>
At the end of the translation, another link can be placed to hide it again:
<a href="javascript:varyDisplay('thediv','none')>OK</a>
You may think that it would be more intuitive to use the words “hide” and “show” in the function calls rather than “none” and “block”, but using the actual values preserves the full flexibility of the property. If I should want to make an element inline (or in the style of a list item) in response to a link, I can do it with the same function without any modification. All right, I can think of no reason why I should want to, but you never know what you may want to do some day, and leaving maximum flexibility (and at no effort) is a good idea.
If you look at the function you will see that after the variables have been declared, it checks to see if getElementById is true — in other words, if the browser is compliant to the W3C DOM standard. If that isn’t true, it then checks for document.all, which is often taken as an indication that the browser is MSIE — although bear in mind that some other browsers will return true for the presence of document.all, and these browsers will probably not behave like MSIE; but here, though, the function is actually checking for something which it will use, we are not trying to detect any given browser. The variable theObj is given the value of the element in question, and that is used to modify the display value of the element.
The alert will have noticed there is something missing. The first part of the if … else construct checks for recent browsers, such as Netscape 6, which comply with the W3C DOM; the second part checks for, roughly speaking, most versions of Internet Explorer in current use. What about Netscape 4? Shouldn’t there also be a bit of code which uses document.layers?
This is where we come to that big caveat that I mentioned earlier: you can’t do this in Netscape 4. Once Netscape 4 has rendered an element, you cannot modify its display property.
There are ways to work around this for Netscape 4, ways which are used by designers producing the heirarchical menus I mentioned at the start of this article. These ways, however, are hideously complex — and as I’ve said, more and more I think extremely complex JavaScript is more trouble than it is worth, particularly if the only purpose of it is to get around the inadequacies of a godsawful, obsolete disaster area of a browser with a shrinking user base. I’ve therefore simply left Netscape 4 out of the equation, although as Netscape 4 users will see both the original and the translation, the page remains usable for them — which is the main goal.
This is the finished code in action:
L’infrastructure du Web a bien résisté à la soudaine montée en puissance du trafic en direction des sites d’information. Il a ainsi pallié les défaillances du réseau téléphonique, saturé après les attaques. Dans ce contexte exceptionnel, il s’est révélé un instrument de communication fiable et rapide.
[English]
The Web’s infrastructure stood up well to the sudden surge in traffic going to news sites. In this way it compensated for the failings of the telephone network, which was saturated after the attacks. In this exceptional situation, it has been shown to be a communications tool which is both reliable and fast.
[OK]
© DC 2001. All rights reserved.


