Categories
Technology Writing

Creating C# Applications: Chapter 3

When I work with more than one programming language at a time, such as Java and Perl or VB and C#, the biggest problem I have keeping the languages untangled is remembering to use a semi-colon (;) or not when ending the statement. No matter how hard I try to keep my language syntax separate, I always include the semi-colon when I shouldn’t (such as in VB), or not include it when I should (such as in C++ or Java or C#).

Regardless of the sophistication of a programming language, you must first become proficient with the operators and special characters supported in the language before advancing on its more escoteric elements, and this chapter provides coverage of C#’s operators and special character set — including the infamous semi-colon.

Arithmetic and Concatenation Characters

The simplest of the operators for C# are the arithmetic operators. The addition operator (‘+’) is used to add two numbers together, as it’s used in most other programming languages, such as C++. In addition, the + operator is an example of an overloaded operator within C#. What this means is that you can use it for adding numbers and you can also use it to add two strings together (concatenation), or add a string and a number. An overloaded operator is one that can work with different parameters, or parameter types. C# extends this capability by also translating parameters to compatible types — such as converting an integer to a string for concatenation when adding a string and an integer.

To demonstrate this capability, in the following code, the addition operator is used to add two numbers and two strings and print out the results of both operations.

using System;

class ArithTest 
{
   public static void Main() 
   {
        int i = 6;
	     string s1 = "Value";
        string s2 = " is ";

        // add two numbers
        i = i + 4;
        
        // add two strings
        s1 = s1 + s2;

        // add a string and a number
	     s2 = s1 + i;

        // output values
        Console.WriteLine(i);
        Console.WriteLine(s1);
        Console.WriteLine(s2);
      
   }
}

The result from running this application is:

10
Value is
Value is 10

The plus sign can’t convert automatically between the two operands if the result is ambiguous, or disallowed for implicit type conversion. If you try to add a double to an integer, as shown in the following line of code:

i = i + 4.15

An error results when you compile the application because you can’t implicitly convert a double to an integer.

The addition operator can also be used to perform delegate concatenation, covered in more detail in Chapter 10 “Delegates and Events”.

The addition operator is both a binary operator, meaning that there are two operands for an expression containing the operator, and a unary operator. A unary operator applies to only one operand. Applying the addition operator as a unary operator to an operand just returns the value of the operand:

nVal = i+;

The subtraction operator (‘-‘) is used to subtract one number from another, or to negate the value of an operand, as demonstrated in the following code:

using System;

class ArithTest 
{
   public static void Main() 
   {
        int i = 6;

        // subtract smaller value
        Console.WriteLine(i - 2);

        // subtract larger value
        Console.WriteLine(i - 7);

        // unary
        Console.WriteLine(-i);
      
   }
}

The following values are output when this application is run:

4
-1
-6

The subtraction operator, as with the other arithmetic operators, works with all numeric data types, such as integers, doubles, and decimals.

The multiplication operator (‘*’) multiplies two operands together, while the division operator (‘/’) divides the first number by the second. The modulus operator (‘%’) returns only the remainder after the first operand is divided by the second.

In the following code, each of the operators just described is used between two different operands, both of which are type double, and the results are printed out:

 
using System;

class ArithTest 
{
   public static void Main() 
   {
        double d1 = 4.15;
        double d2 = 1.23;

        //  multiply
        Console.WriteLine(d1 * d2);

        // divide
        Console.WriteLine(d1 / d2);

        // modulus
        Console.WriteLine(d1 % d2);
      
   }
}

The output of this application is:

5.1045
3.3739837398374
0.46 

The multiplication operator is another example of an overloaded operator; it’s also used when declaring pointers, and de-referencing these pointers to access the pointer values as you’ll see in the section “Membership, Array, and Casting Operators” later in this chapter.

With all arithmetic operations, if an overflow occurs because the result is too large for the allowed range of the data type, an OverflowException is thrown if one of the following conditions is met:

  • The checked compiler option is used and
  • The data types of the operands are integers (int, long, or ulong)
  • Or the operands are decimals

Use the checked compiler option when compiling the application in order to generate an OverflowException with integers. This compiler option turns on arithmetic checking:

csc /checked test.cs

In the following C# application, the OverflowException is captured and the error message printed out:

 
using System;

class ArithTest 
{
   public static void Main() 
   {
        int i = 2147148000;
        int i2 = 32000;

        try 
        {
           //  multiply
           i = i * i2;
           Console.WriteLine(i);
        }
        catch (OverflowException e)
        {
           Console.WriteLine("{0}", e);
        }
      
   }
}

When the application is compiled without the checked option, the following output results:

2144165888

Since integer arithmetic checking isn’t turned on, the significant high-order bits are discarded, and the resulting value is returned. When checking is turned on with the check compiler option, the following exception message is printed out:

System.OverflowException: An exception of type 
   System.OverflowException was thrown.
   at ArithTest.Main() 

The OverflowException will occur with all decimal values when the value is too large for the decimal format.

Float and double values don’t generate an overflow exception. Following the IEEE 754 arithmetic specification, values too large for the variable are set to infinity. If a value can’t be defined as a numeric, it is given the constant NaN — meaning Not a Number.

Arithmetic and concatenation operators are useful for converting values, but have no impact on an application’s process. In addition, each of the variables modified by the operators in this section first had to be assigned. Program flow controlled through the use of logical and condition operators and the assignment operators are discussed next.

Categories
Technology

Creating C# Applications: Chapter 2

If you had a chance to design a programming language from the ground up, what would you include? Would you include support for pointers as C++ does? Or would you support the concept of automatic garbage collection, forming the basis of memory management in Java.

Perhaps you’d support the loose typing implemented in Visual Basic 6.0. Or you could opt for strong type safety, instead. Would you require that the developers pass pointers to the objects; or would you support the concept of marking a parameter as passed by reference and hence modifiable within the function?

The creators of C# at Microsoft have had a chance to look at programming language use in the last several years and ask themselves these questions. The result is an intriguing language that takes bits and pieces of several different development languages and environments and rolls them all into one.

In addition to the design of C#, the language architects also took a look at programming language interoperability, including issues such as data typing across programming languages. As a result of this effort, the Microsoft language architects participated in the design of a programming language infrastructure that supports interoperability between different programming languages, an infrastructure called the Common Language Infrastructure (CLI).

Before getting into more detail on the CLI and its impact on the design of C#, let’s take a quick look at how C# compares with three more commonly used programming languages, C++, and Visual Basic, too.

C#: A little C++, some Java, and a Touch of VB

C# owes its roots to more than one programming language. Specifically, you can see elements of three different languages in its makeup: C++, Java, and Visual Basic (though VB is a development environment and a language). Or perhaps it would be better to say that you can see the roots of programming language design that went into the composition of C++, Java, and VB in addition to other programming languages.

For instance, memory management in Java is handled by automatic garbage collection. However, automatic memory management is also used with LISP and other languages, so the use of garbage collection in C# can be attributed to LISP as much as it can be attributed to Java.

C# supports the concept of passing parameters by reference with the Ref keyword, or passing output parameters using the Out keyword. This concept is similar to the support of input/output parameter with Visual Basic. However, you can see an exact same implementation in Inprise’s Delphi product, based on Pascal. This similarity isn’t too surprising considering that one of the creators of C# is Anders Hejlsberg, formerly of Inprise.

There are also aspects of C# that are unique to it when compared with the more commonly used C++ or Java. For instance, the aspect of C# that intrigues me the most is the language’s support for unmanaged as well as managed code through the use of the unsafe keyword. Though covered in detail in the later chapter, Chapter 17, “Outside the Bounds — Memory Management, Unmanaged Code, and the Use of Unsafe”, I did want to mention it briefly now.

Using unsafe and a companion keyword, fixed, you can mark specific code within a C# application as unmanaged code. Doing this prevents automatic memory collection from occurring in this section of code. The other part of the C# application that isn’t marked as unsafe, can still be managed with automatic garbage collection. This hybrid approach to memory management allows C# developers to use language constructs such as pointers, while still taking advantage of automatic garbage collection techniques to control memory usage.

So, we can view C# as the latest culmination of several years of programming language research — at least, until another language appears on the programming language horizon.

Categories
Technology Writing

Creating C# Applications: Chapter 1

Introduction

There’s been considerable material on programming C# within the Visual Studio .NET environment, but not as much on C# as the first programming language based on the Common Language Infrastructure (CLI).

This online C# book provides an introduction to C#, the programming language. In addition, the book also takes a look at the CLI as well as the Common Language Runtime (CLR), using C# to demonstrate the various aspects of this standards-based development environment.

We’ll explore CLI/CLR in more depth in other chapters, but for now, to get you started, we’ll take a look at the basics necessary to get you up and running with C#.

The Basics

You can’t work with a programming language without learning the basics of creating an application in that language. Some languages, such the version of Basic found in Visual Basic, are a language and development environment tightly bound into one tool. Others, such as C++, can be bound to a development environment (ala Visual C++), or can be worked with using command line compilers and standard text editors, such as C++ within a Unix environment.

Fundamentally, you need to learn how to create the simplest form of an application in the language, compile it, and then run it. Once you have this information, you can then vary your program as you learn new and different aspects of the language.

This chapter provides an overview of how to create and compile a C# application using the minimum environment — in this case, using the .NET Framework SDK that’s downloadable, for free, from the Microsoft web site.

The Structure of a C# Application

Before installing the C# support environment, let’s take a look at a minimal C# application.

A C# application can consist of one or more modules — separately compiled functional units that don’t have a main entry point — libraries (comparable to COM components), and at least one application entry point. A C# file has an extension of .cs, and may, or may not, contain a Main application method.

A minimal C# application can have the following format:

using System;

class someClass
{
   public static void Main() 
   {
   }
}

As you can see, a minimal application doesn’t require a lot of code, requiring only the following:

  • A reference to the System namespace
  • A class
  • A main function within the class, that’s called when the application’s run

Applications written in C# access external functionality through the use of namespaces — a container for classes, structs, types, and other useful programming goodies (namespaces are described in greater detail in a later chapter, “C# Scoping and Namespaces”).

C# files contain one or more class definitions. In addition, the files can also contain other C# elements such as interface definitions, delegates, and enumerations. A stand-alone application also has a Main function, called when the application is run. However, to create and run the application, you first have to install the environment.

The C# Environment

As with Java, C# is dependent on a runtime environment being present in order to support the language. Java depends on the Java Virtual Machine (VM) and C# is dependent on the Common Language Runtime (CLR), a set of services providing security, type safety, cross-language exception handling, garbage collection, and other features. An application that contains code meant to be managed by the CLR is known as managed code; code outside of the CLR control is know, appropriately enough, as unmanaged code.

There are five different CLR hosts that support managed code:

  • ASP.NET (for server-side Web access)
  • Internet Explorer (for code implemented within the boundaries of the browser)
  • VBA (for script executed within the confines of Outlook or Office or other VBA enabled applications)
  • Windows Form Designer
  • Windows Shell EXE (for applications launched by a command line)

The last CLR runtime host is the one we’ll be using throughout this online book, primarily because this host allows us to focus on C# as a language, rather than C# as being part of ASP.NET or Web Services, and so on. Once you have a command of the language, then you can explore the other more complex uses of the language, such as those just mentioned.

In addition, you’ll be using the command line compiler when creating each of the test applications rather than creating the examples within Visual Studio. Again, this puts the focus on the language rather than the development environment. However, to run the application, you first have to compile it, which means you have to have both the infrastructure and compiler installed on your machine.

Categories
Technology

X-Objects: Clipping

Copy found at Wayback Machine archive.

Clipping in the earlier releases of Mozilla and with Navigator 6.0 followed the CSS 2.0 release specification. Clipping boundaries are set at “0” for all four sides of the rectangle containing the content — to clip, you would offset the values, using positive numbers only.

This differed from the original implementation of IE 4.x and up and Navigator 4.x, and the original CSS-P specification submission. With these, the element’s right and bottom clipping value is set to the width and height of the element by default. To offset the top and left, increment the top, left values. To offset the right and bottom, decrement these same values.

Having a different clipping region framework was a challenge when it came to cross-browser development.

However, beginning with Mozilla build M16 (and Navigator 6.0 PR 2.0 and up), clipping for the new browsers is the same as it was for Navigator 4.x and for IE 4.x and up. Supposedly, the W3C will be issuing errata for CSS 2.0 to change the clipping framework to match this common usage.

On to the X-Objects

The X-Object does have several methods exposed on the interface to handle clipping:

  • objSetClipRect – set the clipping values
  • objGetClipRect – get the current clipping value, if any
  • objGetClipLeft – get the clipping rectangle’s left value
  • objGetClipRight – get the clipping rectangle’s right value
  • objGetClipTop – get the clipping rectangle’s top value
  • objGetClipBottom – get the clipping rectangle’s bottom value

Adding support for Mozilla/Navigator 6.0 didn’t change the implementation for clipping with the original cross-browser objects. The implementation for Navigator 4.x is still:

// clip object
function nsobjSetClipRect (top,left,bottom,right) {
	if (top == null) top = this.objGetClipTop();
	if (left == null) left = this.objGetClipLeft();
	if (bottom == null) bottom = this.objGetClipBottom();
	if (right == null) right = this.objGetClipRight();
	this.css2.clip.left = left;
	this.css2.clip.right = right;
	this.css2.clip.top = top;
	this.css2.clip.bottom = bottom;
}

function nsobjGetClipRect () {
   var strng;
   var left = this.css2.clip.left;
   var right = this.css2.clip.right;
   var bottom = this.css2.clip.bottom;
   var top = this.css2.clip.top;

   strng = "rect(" + top + "px, " + right + "px, " + 
                 bottom + "px, " + left + "px)";
   return strng;
}

// get current clip right 
function nsobjGetClipRight() {
	return this.css2.clip.right;
}

// get current clip left
function nsobjGetClipLeft() {
	return this.css2.clip.left;
}

// get current clip top
function nsobjGetClipTop() {
	return this.css2.clip.top;
}

// get current clip bottom
function nsobjGetClipBottom() {
	return this.css2.clip.bottom;
}

Navigator 4.x implemented the clipping values as separate values, which actually made the use of this CSS attribute a little easier than how it was implemented in IE. However, the IE implementation is one that can be shared by Mozilla/Navigator 6.0 — though it is more complicated:

// return clipping rectangle
function domGetClipRect() {
   return this.css2.style.clip;
}

// clip object
function domSetClipRect(top, left, bottom, right) {
   if (top == null) top = this.objGetClipTop();
   if (left == null) left = this.objGetClipLeft();
   if (bottom == null) bottom = this.objGetClipBottom();
   if (right == null) right = this.objGetClipRight();
   strng = "rect(" + top + "px, " + right + "px, " + 
                 bottom + "px, " + left + "px)";
  this.css2.style.clip = strng;
}

	
// clip object on left
function domGetClipLeft() {
	return get_entry(this,"left");
}

// clip object on right
function domGetClipRight() {
	return get_entry(this, "right");
}

// clip object at top
function domGetClipTop() {
	return get_entry(this,"top");
}

// clip object at bottom
function domGetClipBottom() {
	return get_entry(this,"bottom");
}

The main difference between the Navigator 4.x and IE implementation is that the IE treats the clipping property as one setting rather than four distinct settings. Based on this when accessing the existing the clipping property, it has to be parsed to get each of the clipping rectangle’s values.

Microsoft did provide read only properties to access each value of the clipping rectangle. However, as these aren’t usable with Mozilla/Navigator 6.0, I left the code within the object as is, and used parsing.

The parsing is handled through two helper functions, convert and get_entry, which are not exposed on the X-Object’s interface:

// convert string to value
function convert(strng) {
    var i = parseInt(strng);
    return i;
}

// get clipping value for specific dimension
function get_entry(obj,indx) {
	strng = obj.css2.style.clip;
        if (strng.length > 0) {
	   strng = strng.slice(5,strng.length-1);
	   var entries = strng.split(" ");
           }
        else {
            var entries = new Array(5);
            for (i = 0; i < entries.length; i++)
                entries[i] = "auto";
            }
	if (indx == "top") {
		if (entries[0] == "auto") 
                   return 0;
		else
		   return convert(entries[0]);
            }
	else if (indx == "left") {
		if (entries[3] == "auto") 
		   return 0;
		else
		   return convert(entries[3]);
		}
	else if (indx == "bottom"){
		if (entries[2] == "auto") {
		   return obj.objGetHeight();
                   }
		else
		   return convert(entries[2]);
              }
	else if (indx == "right") {
		if (entries[1] == "auto") 
		   return obj.objGetWidth();
		else
		   return convert(entries[1]);
		}
	
}

Let’s try the X-Object clipping functionality, with an example application created specifically for testing clipping.

Clipping Test Application

The test page has two different blocks in the page, each created in separate positioned DIV blocks. The topmost block contains an HTML form and form buttons, used to clip the second block’s left, top, right, and bottom rectangle’s values:

<BODY onload="create_objects(); setup()">
<DIV style="position:absolute; left:10; 
top:10; background-color: yellow; 
layer-background-color: yellow; padding-top: 20px; 
overflow: hidden;
width: 500; height:150; clip: auto">
<form action="">
<center>
<INPUT type="button" value="Clip to the Left" 
   onclick="clip_left()"> 
<INPUT type="button" value="Clip to the right" 
   onclick="clip_right()"><p>
<INPUT type="button" value="Clip on the top" 
   onclick="clip_top()"> 
<INPUT type="button" value="Clip the bottom" 
   onclick="clip_bottom()"><p>
<input type="button" value="Show the clip property" 
   onclick="show_clip()">
</center>
</FORM>
</DIV>

<DIV id="info" style="position:absolute; 
left: 250px; top: 180px; background-color: red; 
  width: 300px; height: 300px; overflow: hidden; 
layer-background-color: red">
<H1>Block with info</H1>
<p>
This is a block that contains two HTML elements: 
a header and a paragraph
</p>
</DIV>
</BODY>

A function is called when the page is loaded, setup, which sets the clipping region of the target DIV block, using values that differ based on browser type:

function setup() {
  
   theobjs["info"].objSetClipRect(0,0,300,300);
   }
}

These values set the clipping region to fit the existing DIV block parameters (300px wide, 300px tall).

The functions to create the clipping effect are:

// clip element
function clip_left() {
   var lft = theobjs["info"].objGetClipLeft();
   lft+= 10;
   theobjs["info"].objSetClipRect(null,lft,null,null);
}

function clip_right() {
   var rt = theobjs["info"].objGetClipRight();
   rt-= 10;
   theobjs["info"].objSetClipRect(null,null,null,rt);
}

function clip_top() {
   var top = theobjs["info"].objGetClipTop();
   top+= 10;
   theobjs["info"].objSetClipRect(top,null,null,null);
}

function clip_bottom() {
   var bt = theobjs["info"].objGetClipBottom();
   bt-=  10;
   theobjs["info"].objSetClipRect(null,null,bt,null);
}

function show_clip() {
   alert(theobjs["info"].objGetClipRect());
}

Try out the Clipping Example for yourself, using IE 4.x and up, Navigator 4.x, or Mozilla/Navigator 6.0.

For more complicated demonstrations of clipping, check out the associated article Demonstrating PhotoShop functionality using DHTML and X-Objects, which has four DHTML demonstrations using various effects, including clipping.
Categories
Technology

X-Objects: Events

Copy found at Wayback Machine Archive.

Event handling is pretty straight forward for all three impacted browsers (or browser object models). Events can be handled using two different techniques: through event handlers attached to HTML elements, or through event capturing. Navigator 4.x, IE, and Mozilla/Navigator 6.x all support both types of event handling, though the extent of coverage and the methods do differ.

Navigator 4.x only supports certain event handlers embedded within certain HTML tags — most notably this browser supports mouse event handlers such as onMouseOver and OnClick primarily within a link element (designated by <A;>). Additionally, Navigator 4.x also supports event capturing, using functionality similar to:

document.captureEvents(Event.KEYPRESS);

document.onKeyPress=keypress;

function keypress(e) {
   tmp = e.which;
   else if (navigator.appName == "Mozilla")

   // if space bar hit
   if (tmp == 32) {
	window.close();
	return;
	}
}

Both IE and Mozilla/Netscape 6.0 support event handlers on HTML elements as defined within the HTML 4.0 specification, at the least. This means that you can associate an onMouseOver event handler with all HTML elements that support this — which means most if not all of them.

Additionally, IE and Mozilla/Netscape 6.0 also support event capturing though the techniques do differ. In IE, you can use SetCapture or ReleaseCapture with HTML elements, and all mouse movements are then passed to the element. You can also assign event handlers to objects in script:

document.onKeyPress=keypress;

With Mozilla/Netscape 6.0, event handling is provided through the DOM Level 2 Events. For instance, to provide event handling for an event, you can add an Event Listener for the object:

document.addEventListener("keyup",keypress,true);

The addEventListener method takes the event as the first parameter, the event handler (function) as the second, and whether the event is captured or allowed to “bubble up” to other events with the third parameter. In the code just shown, the keyup event is captured and assigned to a function called “keypress”.

Within an event handler, you can access an Event object, though how this is accessed and used also differs between the browsers.

With Navigator 4.x, the Event object is passed, automatically, as a parameter to the event handler. Within IE, the Event object is accessed through the Window object during event handling. Mozilla/Netscape 6.0 supports DOM Level 2 event handling. An Event object is passed to the event handler, and information can be pulled from it.

An example of event handling and pulling event information from an Event object is the following, which pulls information about which key is pressed:

function keypress(e) {

   if (navigator.appName == "Microsoft Internet Explorer")
      tmp = window.event.keyCode;
   else if (navigator.appName == "Navigator")
	tmp = e.which;
   else if (navigator.appName == "Mozilla")
       tmp = e.keyCode;

   // if space bar hit
   if (tmp == 32) {
	window.close();
	return;
	}
}

In this code, if the space bar is hit (an ASCII value of 32), the current window is closed. The event handler itself is activated by the following code:

   // capture events
   if (navigator.appName == "Microsoft Internet Explorer")
	wdth = document.body.clientWidth;
   else if (navigator.appName == "Netscape")
   	document.captureEvents(Event.KEYPRESS);
   else
      document.addEventListener("keyup",keypress,true);


   // assign function to event handler
  if (navigator.appName != "Mozilla")
    document.onkeypress=keypress;

Notice that the Mozilla/Netscape 6.0 code captures the keyup event, not the keypress. The reason for this is that the actual key value is set with a keyup or keydown event, but not with keypress. Capturing keypress will give me the ASCII value for the control keys, such as Enter or Tab, but not the other keys such as “N” or the space bar.

Now that we’ve had a brief introduction to X-Object event handling, we’ll take a look at some examples using different types of event handling.

Embedded Event Handlers

The simplest approach to event handling is to embed event handlers right in the HTML element. However, you also have to take into account that Navigator 4.x doesn’t support embedded events for the most part — if you want to capture events such as mouse events, you need to encapsulate the target element within a link.

To demonstrate, I modified a DHTML example application that uses a transparent GIF to embed “hot spots” in a page. When the mouse moves over the hot spot, the transparent image is replaced by a visible image.

Within the page, the transparent images are created within links, which are themselves encapsulated within positioned DIV blocks:

<DIV id=hotspot1>
<a href="" onclick="return false" onmouseover="hotspot(0)">
<img src="blank.gif" width=80 height=32 border=0></a>
</DIV>

When the mouse moves over the image, the hotspot function is called with the number of the spot. This function then replaces the existing transparent GIF with the visible one:

dfltimg = new Image();
dfltimg.src = "logo.gif";

// access images and changing their source
// is relatively old
function hotspot(num) {

   if (navigator.appName == "Microsoft Internet Explorer" ||
       navigator.appName == "Mozilla")
	document.images[num].src = dfltimg.src;
   else
	document.layers[num].document.images[0].src = dfltimg.src;
}

As you might notice from the code, both IE and Mozilla/Netscape 6.0 can access the images array directly, regardless of what container HTML elements the images are in. With Navigator 4.x, however, you have to access the image object directly from the images collection for each document layer in the page.

Try out the HotSpot example yourself, using Mozilla/Netscape 6.0, IE 4.x and up, and Navigator 4.x. Expose the hotspots by moving your mouse over the page (there are 6 of them).

Finding an ASCII value

I have a utility DHTML application that prints the ASCII value of any key pressed to a form text box. I modified this utility to work with Mozilla as well as with Navigator 4.x and IE 4.x and up.

The application captures the keypress event (the keyup event for Mozilla), and attaches this event to an event handler function. The key capture and handling code is:

// handle keyboard events
if (navigator.appName == "Mozilla")
   document.addEventListener("keyup",keypress,true);
else if (navigator.appName == "Netscape")
   document.captureEvents(Event.KEYPRESS);

if (navigator.appName != "Mozilla")
    document.onkeypress=keypress;

// perform action based on keypress and state info
function keypress(e) {

   if (navigator.appName == "Microsoft Internet Explorer")
      tmp = window.event.keyCode;
   else if (navigator.appName == "Navigator")
	tmp = e.which;
   else if (navigator.appName == "Mozilla")
       tmp = e.keyCode;
   document.forms[0].elements[0].value = tmp;
}

You can try out the ASCII Utility yourself using Mozilla/Netscape 6.0, IE 4.x and up, and Navigator 4.x.

One thing you’ll find if you try this example with Mozilla/Netscape 6.0 is that the ASCII key value reflects the value of the key if it were capitalized. So, you get a value of “65” when you press an “A”, regardless of whether you’re pressing the shift key or not. I’m not sure if this is by design or by accident and am investigating this behavior. (Ahh, I do love working with alpha code).

Keep Away

I modified one more DHTML example that uses a combination of embedded event handlers and event capturing to create a “keep away” effect. The example uses an embedded event handler within a DIV block, which works with Mozilla/Netscape 6.0 and IE 4.x and up, but doesn’t with Navigator 4.x:

<DIV id="block" style="left: 200; top: 200; width: 104"
onMouseover="keep_away()">
<img src="yasd.gif" width=104>
</DIV>

To provide event handling for Navigator 4.x, the onMouseOver event for the DIV block is captured in script, and assigned to the same event handler:

:

function capture_events() {
// handle keyboard events
if (navigator.appName == "Netscape") {
	document.block.captureEvents(Event.MOUSEOVER);
      document.block.onmouseover=keep_away;
	}
}

Within the event handling code itself, the CSS positioned DIV block (containing an image of L’il Flame) is moved either right or left, in effect keeping the image away from the user’s mouse:

MAXHORIZ = 700;
MINHORIZ = 100;
var adjustor = 0;

if (navigator.appName == "Navigator") {
   adjustor = 50;
   }
else
   adjustor = 100;

function keep_away() {
	var newleft = theobjs["block"].objGetLeft();
      if (newleft > MAXHORIZ)
		adjustor=-1 * adjustor;
      else if (newleft < MINHORIZ)
		adjustor= -1 * adjustor;
      newleft= newleft+adjustor;
      theobjs["block"].objSetLeft(newleft);
}

As spacing is a bit different between IE and Navigator, the original code provided a different adjustor value for moving the DIV block. I’ve found that the same settings also work with Mozilla. Try the Keep Away example yourself, using Mozilla/Netscape 6.0, IE 4.x and up, and Navigator 4.x. Move your mouse over L’il Flame to cause it to move away from your mouse.