Sick of while?

Experienced programmers who have trudged through the past five pages will probably have frequently asked themselves the questions:

"Hmm. We've learnt about while as a way of repetitively doing things, but what about other ways? Most languages have constructs such as for .. next and so on! In addition, although if .. then .. else makes sense, what about the C++ switch statement as a mechanism for flow control? "

JavaScript has many constructs for 'flow control'. We've deliberately avoided them up to now, because, quite frankly, they are unnecessary (although occasionally convenient). We've really tried to keep to what is necessary, and they are not. We'd go so far as to say that they often impair the readability of code!

But for the record, here they are:

  • for (initialisation ;
              condition ;
               update )
              { /* things to do go here */ };
             

    The idea with for is that a variable is initialised, and then repetitively altered until a condition fails to be met. A sort of while with attitude. We might for example say:

    for ( i = 1; i < 10; i ++ ) { /* do stuff here */ };

    Note that we could increment i before we tested it by saying "++ i"
    instead of "i ++" - try out the two to see the difference!

  • do { /* things to do go here */ }
               while (condition);
             

    This is similar to while, but always does something before the first test is made. Totally unnecessary, and only available in JavaScript 1.2 and above! Avoid it.

  • break

    Allows you to break out of a loop and bash on with the code after the loop. Occasionally useful. Avoid using a label with the break statement, as this silly wrinkle is only available in JavaScript 1.2 and above.

  • continue

    Allows you to jump to the end of the loop and then continue with the loop. Once in a blue moon this may be more useful than confusing to the reader.

  • with ( something )
              {  /* things to do */  };
             

    with has a specific reason for its existence - it's for lazy people. If you don't want to retype an object name again and again, use with and the object name is automatically put in where needed (within the scope of the curly braces). Superficially, this might make things easier to read .. but watch out!

  •  for ( variable in object )
              {  /* things to do */  };
             

    At last .. something that might be useful. This rather cunning construct allows you to make up a name (variable in the above prototype), and then the script magically sets variable to each property of the object. You can work through all the properties of an object without knowing their names!

  •  switch ( expression )
              { case value0 :
                   /* statements for case of value0 */
                   break
    
                case value1 :
                   /* and so on .. */
    
                default:
                   /* default statements if no other case taken */
              };
             

    switch would have been great if it had been introduced in JavaScript 1.0 - unfortunately it only appeared in 1.2. Note that a common error with this statement is to leave out a break statement (did you notice that we did so above?), often with surprising results. Just ask the Java and C++ programmers!

Sick of while? Well, stick with while!


Cookies

Ever signed onto a password-protected website and then noticed that every time you visit the site again, you automatically get signed on (provided you're on the same computer)? Such behaviour shows both the convenience of cookies, and the potential they give the website-designer for keeping tabs on customers. At present though, cookies are more useful than irritating.

Web-pages were initially designed to be stateless - that is, every time you visited the page, you got the same thing. Unfortunately, this sort of behaviour is not very human-friendly, especially if, as in the above example, you have to repeatedly sign onto a web-site. The correct solution is to avoid such paranoid practices on your site, but cookies have other uses.

They work as follows - when a cookie is set, then this information is remembered on your computer inside a file called cookies.txt - the 'cookie jar'. (Find it on your machine)! The next time you request that page, the browser sees the cookie, and sends the information contained in the cookie together with a request for the web-page. The CGI script on the other end then says either "aha. Joe bloggs is visiting my porno site again", or does something useful with the information such as logging you on automatically. Clearly the "thought police" aspect of cookies depends on what information you have provided to the CGI at the other end - it only knows you are Joe Bloggs if you've provided the information; but it might label you as "user 1234" or whatever. There is of course the potential for multiple servers on the other side to pool their cookie-based information. Note that you can turn off cookies in your browser (or, if the worst comes to the worst, replace the cookies.txt file on your machine with a directory called cookies.txt which will prevent the browser from making a file of that name). Most of the time, it's probably more reasonable just to leave the bloody thing enabled. One can be too paranoid.

How does a CGI program set a cookie?

This is easily done by sending a particular header to your browser. The header is called a Set-Cookie header, and sets several attributes of the cookie, including:
  • a name=value pair;
  • an expiry date;
  • a path;
  • a domain;
  • a 'secure' option.

ONLY the name=value pair is mandatory - it contains the data being stored. If the expiry date is not specified, the cookie becomes stale and is thrown away when you finish your browser session; the path attribute forces the browser to associate the cookie with requests for all page requests in any subdirectory of the path. The domain attribute is even more cunning - any host within that domain gets the cookie (but not top level domains like .com or .org - the cookie makers were at least wise enough to prevent this sort of widespread dissemination of information). The secure option when set will only allow the cookie information to be sent over a secure communication channel.

Can I duplicate the above using JavaScript?

We wouldn't be talking about cookies if you couldn't. The syntax is straightforward - we set a cookie using:

document.cookie=CookieDescriptor;

where CookieDescriptor must be in the appropriate format. An example of the format is:

document.cookie="myname=fred; expires=Friday, 13-Oct-2000 12:00:01 GMT"

Similarly, we can retrieve a cookie by just allocating a variable to the value:

thatName=document.cookie

Enter cookie name
and value

Then click this button..

You may want to browse through the source of this page to see exactly how we did the above! See how we set the expiry time for five minutes into the future - if you quickly get out of your browser and then restart it, the cookie will persist; otherwise, wait a bit, exit, restart and .. it's gone. Clearly it's silly to clutter up somebody's cookie jar with cookies they'll never use - set cookies and their expiry times with caution.

What can't we put into a cookie?

Try typing various things into the above cookie container, to test its limits! You'll find that (surprisingly) a variety of punctuation is acceptable. See how multiple values are appended to the cookie, separated by semicolons. If you leave the name field blank, something is still added, but this is unwise - it would be best to ensure that you always set cookies using the name=value format.

(What about the maximum number and sizes of cookies? Most browsers should allow at least 300 cookies, with a maximum of 20 properties, and 4K for each!)

How do I pull out the expiry time?

The simple answer is "You can't" - we don't know of any method you can use to interrogate JavaScript for the time at which a cookie expires. The obvious solution is to set a separate variable equal to the expiry time, and then you can just pull this out of the cookie!

Finding out if the system supports cookies

There is no smart way to do this, apart from simply writing an arbitrary cookie, and then checking that the value you wrote is available by fetching the cookie value!

Animation and Layers

Web pages now have a vast potential for animated images. Unfortunately, due to incompatibilities between MSIE, and Netscape Navigator versions 4 and 6, it's a mess. To efficiently move images about the screen, you need to understand layers in their various (incompatible) incarnations.

1. Layers in Netscape

Netscape decided to define several new tags (including <LAYER>, <ILAYER> as well as their closures and the <NOLAYER> and </NOLAYER> tags), starting from NN 4.0. In order to make their new navigator, NN 6.x fully compliant with the W3C DOM specifications, they have now abandoned these tags!! If you want to read about how they (used to) work, with a demonstration, then
click here.

2. Layers in MS Internet Explorer!

Try our
MSIE example

If you went to the bother of trying the Netscape layer example, you would have seen that it was actually rather straightforward. More's the pity that Netscape themselves (egged on by the W3C) have abandoned this simple approach.

Look at the plethora of features available if you click on the "Try me" button in our MSIE example. Contrast this with the Netscape version (view it in a Netscape browser).

A universal page

Try this page - it should work with MSIE 4.x(+) and with Netscape 4.x. As soon as we've had a good look at NN 6.x, we'll update it to work there too! See how NN also understands the <div id="xx" style="yy"> tag, which we used in this common page, but access through JavaScript is different from that of MSIE. {This section still needs a lot more work}.

ECMA 262

This is the (complex and difficult-to-read) standard that defines how JavaScript should look and work. You can download a
PDF version of 'EcmaScript' if you click on this link, but don't bother unless you are conversant with Backus-Naur Form (BNF) and have a fair smattering of Perl regex too!

Which version of javascript?

Newer versions of JavaScript seem to be appearing all the time. Avoid writing code that is incompatible with older versions if you possibly can. In other words, unless you absolutely MUST have a certain feature, write code that will work on the lowest version - 1.0 !

Let's look at the major versions:

  1. Version 1.0 - This is found in Netscape version 2. It's really not too bad, although if you try and feed it 1.1 or especially 1.2 code, it may crash horribly. The Microsoft 'equivalent' is perhaps the JScript 1.x of Internet Explorer 3.x, which as we've said should be avoided.

  2. Version 1.1 - Now we're cooking. This is the version of JavaScript found in Netscape Navigator 3.x.

  3. Version 1.2 is the JavaScript version for Netscape version 4.0x (excluding version 4.06). Netscape Navigator versions 4.5x and up support at least JavaScript 1.3. The Microsoft JScript version corresponding to JavaScript 1.2 is JScript 3.x (Microsoft seems to have jumped from JScript 1 to 3 to 5).

    Both JavaScript 1.3 and JScript 3.x are compliant with ECMA-262; note that JavaScript 1.2 is almost compliant (but not totally, as it has some trouble with unicode and with platform-specific date-handling). Internet Explorer version 5.x sports JScript 5.x; in addition you can upgrade your JScript version for IE without upgrading the explorer - so for example, you can run JScript 5.x with IE 3.0 !

    Basically if you've got JavaScript 1.2 or JScript 3.x, you're more-or-less OK. For full 'EcmaScript' compatibility, you need JavaScript 1.3(+) or JScript 3.0(+). Note that if you have a Mac, there is a host of buggy versions of Internet Explorer that you should avoid like poison (Now why should this be?)

Here's a cute way of checking the JavaScript version:

Checking the JavaScript version

 <script language='JavaScript'>
 <!--
 JSver = "1.0";
 //-->
 </script>

 <script language='JavaScript1.1'>
 <!--
 JSver = "1.1";
 //-->
 </script>

 <script language='JavaScript1.2'>
 <!--
 JSver = "1.2";
 //-->
 </script>

 <script language='JavaScript'>
 <!--
 alert("I see you're using JavaScript Version " + JSver);
 //-->
 </script>

The variable is only updated to 1.1 or 1.2 if the corresponding scripts are run, and they are only run if the version matches! Pretty, isn't it?

Turning to a different issue, the WWW Consortium has made recommendations for the JavaScript DOM. Level zero is met by NN 3.x and IE 3.x , and level 1, and more recently (November 2000) level 2, are now recommendations.


Miscellaneous NaNs and tildes

  1. We never told you what a tilde (~) does! It takes a binary number, and changes all the zeroes to ones and vice versa. In other words, it gives you the complement of the number. Note that this is a ones complement (different from the negative or two's complement of a number, which does a ones complement and then adds one). You'll probably never use it.

  2. NaN stands for "Not a Number". You'll encounter it from time to time, usually when you've done something wrong, or JavaScript thinks that you have. What we didn't tell you is that there is a function called isNaN() which returns true if the argument passed to it is not a number.

  3. The escape() function has its uses. What does it do? It encodes a string passed to it, returning something (a string) in a suitable form to be passed as the query string of a URL. The function unescape() undoes this encoding.

  4. Tainting is something a bit beyond this tutorial (at present) but basically involves flagging a language element as 'tainted', so that is cannot be disclosed to a host other than from where it came. One can untaint elements as well.

  5. Event emulation may occasionally be of use - many objects have associated methods that allow you to simulate what would happen were you to say, click on a button. Unsurprisingly, the method in this instance would be click().

  6. The history property of a window could be used to move forward or back, just as if you had pressed the corresponding navigator buttons. The methods that do this are forward() and back(). The go() method is a little more interesting. If supplied with an integer, it goes that number of pages ahead (positive integer) or back (negative). If supplied with zero, it reloads the page. A cute wrinkle is that if supplied with a string, it loads the closest page which contains that string as part of its URL.

  7. Did you know that you can invoke Java (yes, Java) methods directly from JavaScript? We won't go into this in any detail, just give an example (but note that this doesn't work in IE, only Netscape):

    java.lang.System.out.println("Oh Sh*t!");

    Open the Java Console (click on Communicator|Tools, or Options.., depending on the version) and you will see "Oh Sh*t!" displayed there. All the little bits which were left out of JavaScript - well, if you know Java, you can invoke them! In Netscape, open the Java console, and then click on the button below:

In conclusion?

On our
final page we'll look at event handling in more detail for both Navigator and Internet Explorer. We'll also give a few pointers to the vast amount there still is to learn!


Webpage author jvs@anaesthetist.com Last update: 2000-10-7