JMU
Client-Side ECMAScript/JavaScript Programming
An Introduction with Examples in HTML


Prof. David Bernstein
James Madison University

Computer Science Department
bernstdh@jmu.edu


Overview
Important Aspects of the ECMAScript/JavaScript Bindings
Accessing Nodes
Accessing Nodes

A Simple Example Click here for a demonstration.

ecmascriptexamples/clientsidebasics/access.html
        <!DOCTYPE html>
<html>
  <body>
    <label>Weight:<input type="text" id="weight" value="100" /></label>

    <script type="text/javascript">
      var weightField = document.getElementById("weight");

      alert("value in the weight input: " + weightField.value);
    </script>
  </body>
</html>
        
Event-Driven Programming
Important Events in Client-Side ECMAScript
Event Handlers
Event Handlers (cont.)
An Example of Event Handling - The Functions
ecmascriptexamples/clientsidebasics/bmi.js
        /**
 * A function to calculate and display the body mass index (BMI)
 *
 * @param {number} weight - The weight in pounds
 * @param {number} height - The height in pounds
 */
function calculateBMI(weight, height)
{
   "use strict"; // ECMAScript 5
   var bmi;
   
   bmi = weight / (height * height) * 703;

   if (bmi < 15){
      bmi = 15;
   }else if (bmi > 60){
      bmi = 60;
   }

   return bmi;
}
        
An Example of Event Handling - The Functions (cont.)
ecmascriptexamples/clientsidebasics/bmi-display.js
        /**
 * Display the BMI in an alert dialog
 *
 * This functions assumes that the document contains two text input
 * elements, one with an id of weight and the other with an id of height
 */
function displayBMI()
{
   "use strict"; // ECMAScript 5
   var bmi, height, heightField, weight, weightField;
   
   weightField = document.getElementById("weight");
   heightField = document.getElementById("height");
   
   weight = weightField.value;
   height = heightField.value;
   
   bmi = calculateBMI(weight, height);
   
   alert(bmi);
}
        
An Example of Event Handling (cont.)

Using Attributes Click here for a demonstration.

ecmascriptexamples/clientsidebasics/handler-attribute.html
        <!DOCTYPE html>
<html>
  <head>
  <script src="bmi.js"          type="text/javascript"></script>
  <script src="bmi-display.js"  type="text/javascript"></script>
  </head>

  <body>
    <label>Weight (pounds):<input type="text" id="weight" /></label><br/>
    <label>Height (inches):<input type="text" id="height" /></label><br/>
    <button onclick="displayBMI();">Calculate</button>
  </body>
</html>
        
An Example of Event Handling (cont.)

Using Properties Click here for a demonstration.

ecmascriptexamples/clientsidebasics/handler-property.html
        <!DOCTYPE html>
<html>
  <head>
  <script src="bmi.js"          type="text/javascript"></script>
  <script src="bmi-display.js"  type="text/javascript"></script>
  <script src="bmi-property.js" type="text/javascript"></script>
  </head>

  <body>
    <label>Weight (pounds):<input type="text" id="weight" /></label><br/>
    <label>Height (inches):<input type="text" id="height" /></label><br/>
    <button id="calculate">Calculate</button>

    <script type="text/javascript">assignHandlers();</script>
  </body>
</html>
        
An Example of Event Handling Using Properties (cont.)
ecmascriptexamples/clientsidebasics/bmi-property.js
        /**
 * The entry point of the BMI calculator
 *
 */
function assignHandlers()
{
   "use strict";
   var calculateButton;

   calculateButton = document.getElementById("calculate");
   calculateButton.onclick = displayBMI;
}
        
Event Handlers - Scope and Related Issues
Event Handlers - Avoiding the Extended Scope Chain
An Example (cont.)

Using Registration Click here for a demonstration.

ecmascriptexamples/clientsidebasics/handler-register.html
        <!DOCTYPE html>
<html>
  <head>
  <script src="bmi.js"          type="text/javascript"></script>
  <script src="bmi-display.js"  type="text/javascript"></script>
  <script src="bmi-register.js" type="text/javascript"></script>
  </head>

  <body>
    <label>Weight (pounds):<input type="text" id="weight" /></label><br/>
    <label>Height (inches):<input type="text" id="height" /></label><br/>
    <button id="calculate">Calculate</button>

    <script type="text/javascript">registerHandlers();</script>
  </body>
</html>
        
An Example Using Registration (cont.)
ecmascriptexamples/clientsidebasics/bmi-register.js
        /**
 * Register the event handlers
 */
function registerHandlers()
{
   "use strict"; // ECMAScript 5   
   var calculateButton;

   calculateButton = document.getElementById("calculate");

   /* Since the last parameter is true, the event must be generated
      by the button (i.e., it will not be called if the event bubbles 
      up from a descendant) */
   calculateButton.addEventListener("click", displayBMI, true);   
}
        
Manipulating the Presentation/Style of the Document
Changing the Stylesheet
An Example of Changing the Stylesheet

An Example Click here for a demonstration.

ecmascriptexamples/clientsidebasics/stylesheet-change.html
        <!DOCTYPE html>
<html>
  <head>
    <title>Some Courses Taught by David Bernstein</title>
    <meta charset="UTF-8">
    <link rel="stylesheet" type="text/css" id="stylesheet" href="modern.css" />
    <script type="text/javascript" src="stylesheet-change.js"></script>
  </head>

  <body>

    <header>
      <img src="bernstdh.png" />
      <p>
      Some Courses Taught by David Bernstein
      </p>
    </header>

    <section>
      <h1>Core/Required Courses</h1>

      <section>
      <h2>CS345</h2> <h2>Software Engineering</h2>

      <p>
      Software engineering is the application of theories, methods and
      tools to the specification, design, creation,
      verification/validation, deployment, operation, and maintenance
      of software products. This course provides an overview of the
      engineering methods, processes, techniques and measurements used
      in the software industry. After completing this course, students
      will have gained some experience with these concepts should be
      able to explain their advantages and disadvantages, and should
      be able to apply them.
      </p>
      </section>
    </section>

    <section class="category">
      <h1>Electives</h1>

      <section>
      <h2>CS488</h2> <h2>Computer Graphics Applications</h2>

      <p>
      This course is an introduction to 2-D and 3-D computer graphics
      that covers the material from the bottom up. That is, it starts
      with the mathematical foundations, then explores the algorithmic
      issues that arise when implementing those mathematical concepts,
      and then considers the practice of developing graphical
      applications (using existing libraries).
      </p>
      </section>
    </section>


    <footer>
      <p>
      Copyright (c) 
      <a href="http://www.jmu.edu">James Madison University</a>.
      </p>
    </footer>

    <script type="text/javascript">registerHandlers();</script>
  </body>
</html>
        
An Example of Changing the Stylesheet (cont.)
ecmascriptexamples/clientsidebasics/stylesheet-change.js
        /**
 * Change the stylesheet
 */
function changeStyleSheet()
{
   "use strict"; // ECMAScript 5
   var current, file, path, pathEnd, sheet;
   

   
   sheet   = document.getElementById("stylesheet");   
   current = sheet.href;
   pathEnd = current.lastIndexOf("/");
   path    = current.substring(0, pathEnd+1);
   file    = current.substring(pathEnd+1);
   
   if (file === "traditional.css") {
      current = path+"modern.css";
   } else {
      current = path+"traditional.css"; 
   }

   sheet.href = current;
}

/**
 * Register the event handlers
 */
function registerHandlers()
{
   "use strict"; // ECMAScript 5

   document.body.addEventListener("click", changeStyleSheet, true);   
}

        
Changing the Style Attribute of an Individual Element
An Example of Changing the Style Attribute

An Example Click here for a demonstration.

ecmascriptexamples/clientsidebasics/styleattribute-change.html
        <!DOCTYPE html>
<html>
  <head>
    <title>Some Courses Taught by David Bernstein</title>
    <meta charset="UTF-8">
    <link rel="stylesheet" type="text/css" href="modern.css" />
    <script type="text/javascript" src="styleattribute-change.js"></script>
  </head>

  <body>

    <header>
      <img src="bernstdh.png" />
      <p>
      Some Courses Taught by David Bernstein
      </p>
    </header>

    <section>
      <h1>Core/Required Courses</h1>

      <section>
      <h2>CS345</h2> <h2>Software Engineering</h2>

      <p>
      Software engineering is the application of theories, methods and
      tools to the specification, design, creation,
      verification/validation, deployment, operation, and maintenance
      of software products. This course provides an overview of the
      engineering methods, processes, techniques and measurements used
      in the software industry. After completing this course, students
      will have gained some experience with these concepts should be
      able to explain their advantages and disadvantages, and should
      be able to apply them.
      </p>
      </section>
    </section>

    <section class="category">
      <h1>Electives</h1>

      <section>
      <h2>CS488</h2> <h2>Computer Graphics Applications</h2>

      <p>
      This course is an introduction to 2-D and 3-D computer graphics
      that covers the material from the bottom up. That is, it starts
      with the mathematical foundations, then explores the algorithmic
      issues that arise when implementing those mathematical concepts,
      and then considers the practice of developing graphical
      applications (using existing libraries).
      </p>
      </section>
    </section>


    <footer>
      <p>
      Copyright (c) 
      <a href="http://www.jmu.edu">James Madison University</a>.
      </p>
    </footer>

    <script type="text/javascript">registerHandlers();</script>
  </body>
</html>
        
An Example of Changing the Style Attribute (cont.)
ecmascriptexamples/clientsidebasics/styleattribute-change.js
        /**
 * Change the stylesheet
 */
function increaseFontSize()
{
   "use strict";  // ECMAScript 5
   var size;
   
   size = parseFloat(document.body.style.fontSize);
   if ((size <= 0) || isNaN(size)){size = 12;}
   
   document.body.style.fontSize = (size * 1.1) + "pt";
}


/**
 * Register the event handlers
 */
function registerHandlers()
{
   "use strict";  // ECMAScript 5

   document.body.addEventListener("click", increaseFontSize, true);   
}

        
Changing the Class of an Individual Element
An Example of Changing the Class

An Example Click here for a demonstration.

ecmascriptexamples/clientsidebasics/class-change.html
        <!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8"> 
    <link rel="stylesheet" type="text/css" href="class-change.css" />  
    <title>Changing the class of an Element</title>

    <script src="class-change.js" type="text/javascript"></script>
  </head>

  <body>
    <p>
      <label>Weight (pounds):</label>
      <input type="text" id="weight" class="valid" />
    </p>

    <script type="text/javascript">registerHandlers();</script>
  </body>
</html>        
An Example of Changing the Class (cont.)
ecmascriptexamples/clientsidebasics/class-change.css
        .invalid {
  color: rgb(153,0,0);
}

.valid {
  color: rgb(0,153,0);
}
        
An Example of Changing the Class (cont.)
ecmascriptexamples/clientsidebasics/class-change.js
        /**
 * Register the event handlers
 */
function registerHandlers()
{
   "use strict"; // ECMAScript 5
   var weightField;

   weightField = document.getElementById("weight");
   weightField.addEventListener("input", validateWeight, true);   
}


/**
 * Validate the weight field
 */
function validateWeight()
{
   "use strict"; // ECMAScript 5
   var weight, weightField;

   weightField = document.getElementById("weight");
   weight      = parseInt(weightField.value, 10);
   
   if (isNaN(weight) || (weight < 0)){
      weightField.className = "invalid";      
   }else{
      weightField.className = "valid";
   }
}

        
Changing a Rule
Changing the Document
Manipulating Nodes in the Document Tree
  1. Get the Node of Interest:
    • Directly: node = document.getElementById("result");
    • First Child: node = parent.firstChild
    • Another Child: node = parent.childNodes[i]
  2. If Necessary, Construct a Node:
    • For example newTextNode = document.createTextNode("...");
  3. Make the Changes:
    • For example parent.replaceChild(node, newTextNode); or parent.appendChild(newTextNode);
    • For example node.data = "..."; or node.nodeValue = "...";
    • For example, the non-standard node.innerHTML = "...";
An Example of Manipulating Nodes

An Example that Modifies Nodes Click here for a demonstration.

ecmascriptexamples/clientsidebasics/bmi-calculator.html
        <!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8"> 
    <link rel="stylesheet" type="text/css" href="bmi-calculator.css" />  
    <title>BMI Calculator</title>

    <script src="bmi.js"            type="text/javascript"></script>
    <script src="bmi-calculator.js" type="text/javascript"></script>
  </head>

  <body>
    <section>
    <p class="input">
      <label>Weight (pounds):</label>
      <input type="text" id="weight" />
    </p>
    <p class="input">
      <label>Height (inches):</label>
      <input type="text" id="height" />
    </p>
    </section>

    <section class="output">
    <p class="output">
       <label>BMI:</label>
       <span id="bmi">&nbsp;</span>
    </p>
    <p class="output">
      <label>Category:</label>
      <span id="category">&nbsp;</span>
    </p>
    </section>

    <script type="text/javascript">registerHandlers();</script>
  </body>
</html>
        
An Example of Modifying Nodes (cont.)
ecmascriptexamples/clientsidebasics/bmi-calculator.css
        .normal {
  color: rgb(0, 101, 0);
  text-transform: capitalize;
}

.obese {
  color: rgb(204,0,0);
  text-transform: capitalize;
}

.overweight {
  color: rgb(255,153,0);
  text-transform: capitalize;
}

.underweight {
  color: rgb(255,153,0);
  text-transform: capitalize;
}

body {
  color: rgb(102,153,204);
  font-family: Arial;
}

input {
  text-align: right;
  border-color: rgb(102,153,204);
  border-radius: 5px;
  border-style: solid;
  border-width: 1px;
}

input:focus {
  background-color: rgb(255,255,204);
}

label {
  float: left;
  text-align: right;
  width: 50%;
}

p.input {
  margin: 0px;
  padding: 5px;
  text-align: right;
}

p.output {
  padding: 5px;
  text-align: right;
}

section {
  width: 400px;
}

section.output {
  background:    rgb(255,240,220);
  border-color:  rgb(110,110,100);
  border-radius: 5px;
  border-style:  solid;
  border-width:  1px;
}

span {
  float: right;
  text-align: right;
  width: 50%;
}

        
An Example of Modifying Nodes (cont.)
ecmascriptexamples/clientsidebasics/bmi-calculator.js
        /**
 * Note: This is a good example of a situation in which an object-oriented
 * approach is preferred. Such an approach would enable us to retrieve the
 * fields once and then store them as properties of the object.
 */

/**
 * Register the event handlers
 */
function registerHandlers()
{
   "use strict";   // ECMAScript 5
   var heightField, weightField;

   weightField = document.getElementById("weight");
   heightField = document.getElementById("height");

   weightField.addEventListener("input", displayResults, true);   
   heightField.addEventListener("input", displayResults, true);   
   
}


/**
 * Display the results
 */
function displayResults()
{
   "use strict";   // ECMAScript 5
   var category, categoryDisplay, bmi, bmiDisplay, height, heightField, text, weight, weightField;
   

   weightField = document.getElementById("weight");
   heightField = document.getElementById("height");
   
   weight = parseFloat(weightField.value);
   height = parseFloat(heightField.value);

   // Clear the current results
   bmiDisplay      = document.getElementById("bmi");
   categoryDisplay = document.getElementById("category");

   text = bmiDisplay.firstChild;
   text.data = " ";
   text = categoryDisplay.firstChild;
   text.data = " ";

   // Calculate the BMI
   bmi = calculateBMI(weight, height);
   
   // Display the results
   if (!isNaN(bmi)){
      text = bmiDisplay.firstChild;
      text.data = bmi.toFixed(1);
      
      text = categoryDisplay.firstChild;
      category = "normal";
      if      (bmi <= 18.5 ){
         category = "underweight";
      }else if ((bmi >= 25) && (bmi < 30.0)){
         category = "overweight";
      }else if (bmi > 30){
         category = "obese";
      }
      
      text.data                 = category; // It will be capitalized
      categoryDisplay.className = category;
      
      
      /* Note: We could have changed the style property rather
         than the class, but this approach is better because it
         delegates all presentation decisions to the stylesheet. */
   }
}

        
Another Example of Manipulating Nodes

An Example that Adds Nodes to the Tree Click here for a demonstration.

ecmascriptexamples/clientsidebasics/addnodes.html
        <!DOCTYPE html>
<html>
  <head>
    <link rel="stylesheet" type="text/css" href="addnodes.css" />

    <script src="addnodes.js" type="text/javascript"></script>
    <title>Add Nodes to the Document Tree</title>
  </head>
  <body>
    <section id="prices">
      <h1>Prices</h1>
    </section>

    <script type="text/javascript">
    start();
    </script>
  </body>
</html>
        
An Example of Adding Nodes (cont.)
ecmascriptexamples/clientsidebasics/addnodes.css
        h1 {
    background: rgb(102,153,204);
    border-color: rgb(102,153,204);
    border-style: solid;
    border-width: 1px;
    border-top-left-radius: 5px;
    border-top-right-radius: 5px;
    color: white;
    font-size: 14pt;
    text-align: center;
    margin: 0px;
    padding: 0px;  
}

input:focus {
    background-color: rgb(255,255,204);
}

input {
    border-color: rgb(102,153,204);
    border-style: solid;
    border-width: 1px;
    border-radius: 5px;
    display: block;
    margin: 5px;
    margin-left: auto;
    margin-right: auto;
    width: 90%;
}

section {
    border-color: rgb(102,153,204);
    border-radius: 5px;
    border-style: solid;
    border-width: 1px;
    float: left;
    margin: 5px;
}
        
An Example of Adding Nodes in the Tree (cont.)
ecmascriptexamples/clientsidebasics/addnodes.js
        function start()
{
   "use strict"; // ECMAScript 5
   var child, i, prices, size;

   size   = window.prompt("Size?");
   prices = document.getElementById("prices");

   for (i=0; i<size; ++i){
      child = document.createElement("input");
      child.type = "text";
      child.value = "";
      prices.appendChild(child);
   }
}
        
Other Important Properties of the Document Object
Other Important Properties (cont.)
Some Useful Functions
Timers
Timers (cont.)
A Timer Example

A Simple Example of Delayed Execution Click here for a demonstration.

ecmascriptexamples/clientsidebasics/splashscreen.html
        <!DOCTYPE html>
<html>
  <head>
    <title>An Example of a Splash Screen</title>
    <meta charset="UTF-8">
    <link rel="stylesheet" type="text/css" href="splashscreen.css"/>

    <script src="splashscreen.js"            type="text/javascript"></script>
  </head>


  <body>

    <header id="splashscreen" class="centered">
     <img src="MultimediaBookCover.png" />
    </header>

    <section>
      <h1>Sampled Static Visual Content</h1>
      <p>
      The sampling of static visual content involves the sampling of
      both the color spectrum and space (usually in that order).  The
      two are similar in that they both involve the discretization of
      continuous information.  They are different in their
      dimensionality.
      </p>

      <dl>
      <dt>Color Sampling</dt>
      <dd>
      A process for converting from a continuous (infinite) set of 
      colors to a discrete (finite) set of colors.
      </dd>
      </dl>

      <p>
      Such processes are sometimes called
      quantization schemes.  The result of color sampling (i.e., the
      discrete set of colors) is often referred to as
      a <em>palette</em>, though one has to be somewhat careful
      because this term is sometimes used to describe the set of
      actual samples and other times is used to describe the set of
      all possible samples.
      </p>
    
      <dl>
      <dt>Spatial Sampling</dt>
      <dd>
      A process for discretizing space.
      </dd>
      </dl>

      <p>
      Though there are many ways to perform spatial sampling, this
      book limits its attention to the plane and, in particular, with
      spatial sampling schemes that involve the use of a finite grid
      with cells of equal size.  In essence, one places a regular grid
      on a planar surface and assigns a single color to each cell in
      the grid.
      </p>

      <p> 
      The result of color sampling and spatial sampling is a
      matrix/table of picture elements (or <em>pixels</em>), each of
      which contains a single color in the palette.  Such a
      matrix/table is often called a <em>raster
      representation</em>. One example is
      illustrated in the following Figure.  In practice, sampled
      static visual content is usually created in one of two ways.  In
      some cases, it is created using a <em>scanner</em> that samples
      from a source of some kind (e.g., a drawing or painting).  In
      other cases, it is created on a computer by a person (who
      selects colors from a discrete set) using a
      pointing device of some kind (e.g., a mouse or a pen on a
      graphics tablet) that performs the spatial sampling.  Two common
      examples of sampled static visual content are <em>bitmapped
      images</em> and <em>bitmapped fonts</em>.
      </p>

      <figure>
        <img src="raster.png"/>
        <figcaption>
        A Raster Representation
        </figcaption>
      </figure>

    </section>
    <script type="text/javascript">splash();</script>
  </body>
</html>
        
A Delayed Execution Example (cont.)
ecmascriptexamples/clientsidebasics/splashscreen.css
        .centered {
    text-align: center;
}

.excluded {
    display: none;
}

section {
    display: none;
}

        
A Delayed Execution Example (cont.)
ecmascriptexamples/clientsidebasics/splashscreen.js
        /**
 * Setup the timer
 */
function splash()
{
   "use strict"; // ECMAScript 5
   
   window.setTimeout(removeSplashScreen, 2000);
}


/**
 * Remove the splash screen
 */
function removeSplashScreen()
{
   "use strict"; // ECMAScript 5
   var i, section, splashScreen;

   splashScreen = document.getElementById("splashscreen");

   /* Append to the className property in case the element
      already has a class for other purposes */
   splashScreen.className += " excluded";

   /* Make the sections "visible" */
   section = document.getElementsByTagName("section");
   for (i=0; i<section.length; ++i)
   {
      section[i].style.display = "block";
   }
}
        
Another Timer Example

A Simple Example of Repeated Execution Click here for a demonstration.

ecmascriptexamples/clientsidebasics/fishtank.html
        <!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8"> 
    <link rel="stylesheet" type="text/css" href="fishtank.css" />  
    <title>Fishtank</title>

    <script src="fishtank.js"            type="text/javascript"></script>
  </head>

  <body>
    <section id="tank">
    <img src="fish.png" id="fish" />
    </section>

    <script type="text/javascript">setup();</script>
  </body>
</html>        
A Repeated Execution Example (cont.)
ecmascriptexamples/clientsidebasics/fishtank.css
        img#fish {
  position: absolute;
  left:     0px;
  top:      200px;
}

section#tank {   
  background: blue;
  background-image: url('ocean.png');
  height:     480px;
  position:   absolute;
  width:      640px;
}        
A Repeated Execution Example (cont.)
ecmascriptexamples/clientsidebasics/fishtank.js
        var fishTimer;

/**
 * Setup the timer
 */
function setup()
{
   "use strict"; // ECMAScript 5
   
   fishTimer = window.setInterval(move, 40);
}


/**
 * Move the fish
 */
function move()
{
   "use strict"; // ECMAScript 5
   var fish, left;

   fish = document.getElementById("fish");

   if ((fish.style.left === undefined) || (fish.style.left === "")){
      left = 0;
   }else{
      left = parseInt(fish.style.left, 10);
   }
   
   left += 1;
   if (left > 400){window.clearInterval(fishTimer);}
   
   fish.style.left = left+"px";
}
        
CSS Transitions instead of Timers
An Example of CSS Transitions

A Simple Example Click here for a demonstration.

ecmascriptexamples/clientsidebasics/ghost.html
        <!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8"> 
    <link rel="stylesheet" type="text/css" href="ghost.css" />  
    <title>A Ghost (Using CSS Transitions)</title>

    <script src="ghost.js"            type="text/javascript"></script>
  </head>

  <body>
    <section id="campus">
      <img src="ghost.png"  id="ghost"/>
    </section>

    <script type="text/javascript">setup();</script>
  </body>
</html>
        
An Example of CSS Transitions (cont.)
ecmascriptexamples/clientsidebasics/ghost.css
        img#ghost {
  left:       0px;
  position:   absolute;
  top:        200px;
  transition: all 4s;
}

section#campus {   
  background-image: url('wilson-hall.png');
  height:     375px;
  position:   absolute;
  width:      525px;
}        
An Example of CSS Transitions (cont.)
ecmascriptexamples/clientsidebasics/ghost.js
        /**
 * Setup the event listener
 */
function setup()
{
   "use strict"; // ECMAScript 5
   var    campus;
   
   campus = document.getElementById("campus");
   campus.addEventListener("click", moveGhost, true); 
}


/**
 * Move the ghost to its final position.
 *
 * Not: The CSS transition will handle the tweening (i.e., the
 * interpolation)
 */
function moveGhost(event)
{
   "use strict"; // ECMAScript 5
   var     ghost;

   if (!event){event = window.event;}
   
   ghost = document.getElementById("ghost");
   ghost.style.left = event.clientX + "px";
   ghost.style.top  = event.clientY + "px";
}