Using JavaScript to Manipulate Elements






Using JavaScript to Manipulate Elements

In the world of Dynamic HTML, one of the most important tags you'll use is <div>. This tag is just a container into which you can put other elements. In Lesson 9, you saw that I used <div>s for just about everything. In Dynamic HTML, you'll see the very same thing. It's perfect because it enables you to group together some elements without any extra formatting baggage.

Once you've placed content within a <div> (or any other block level element), you can use JavaScript to manipulate its properties in the same way you set those properties when the page is displayed using CSS.

Back in Lesson 9, you learned how to place elements you want to apply styles to inside a <div>, and how to position those elements using CSS. Now we can combine that knowledge with the JavaScript you've learned and start putting the dynamic in Dynamic HTML.

Let's look at some basic techniques that will serve you well when you build your own DHTML applications.

Hiding and Revealing Elements

One CSS property that I haven't talked about yet is visibility. The two values for this attribute that you'll use are hidden and visible. Manipulating this property using JavaScript enables you to hide or reveal elements on a page.

I'm going to modify a page with the two overlapping elements so that if you click on one of the menus of links, the other is hidden. The results appear in Figure.

Input

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>DHTML Test</title>
<script language="JavaScript">

function hideMenu(idToHide)
{
  if (document.childNodes)
  {
    document.getElementById(idToHide).style.visibility = 'hidden';
  }
}

</script>

<style type="text/css">
  #menu
  {
    font-family: Verdana, sans-serif;
    padding: 10px;
    border: 1px solid black;
    background-color: #ffc;
    width: 150px;
    position: absolute;
    top: 50px;
    left: 50px;
    z-index: 5;
  }

  #menu2
  {
    font-family: Verdana, sans-serif;
    padding: 10px;
    border: 1px solid black;
    background-color: #cff;
    width: 150px;
    position: absolute;
    top: 100px;
    left: 100px;
    z-index: 1;
  }
</style>
</head>
<body>
<div onclick="hideMenu('menu2');" id="menu"><b>Links</b><br />
<a href="http://www.yahoo.com/">Yahoo</a><br />
<a href="http://www.salon.com/">Salon</a><br />
<a href="http://www.slashdot.org/">Slashdot</a><br />
</div>
<div onclick="hideMenu('menu');" id="menu2"><b>More Links</b><br />
<a href="http://www.google.com/">Google</a><br />
<a href="http://www.slate.com/">Slate</a><br />
<a href="http://www.wired.com/">Wired</a><br />
</div>
</body>
</html>

Output

3. Overlapping absolutely positioned elements. Clicking on one of the menus hides the other.


When a user clicks on one of the menus, the other menu is hidden. One thing you'll notice about this page is that as soon as you click on one of the menus, you're out of luck because the other one is hidden and you can't get it back. You could easily add a button to the page that calls a function to reveal them both again if you wanted. We'll look at some other ways to manipulate them soon.

The style sheets and <div> elements should look pretty standard. The onclick event handler included in the <div> tag for each menu calls a function called hideMenu(), and passes the ID of the menu to hide as a parameter. In the hideMenu() function, we first test for the presence of document.childNodes, which indicates that the browser has DOM support. If it does, we use document.getElementById to get a reference to the menu we want to hide, and I set the visibility property to hidden.

Moving Objects Around

As you've seen, it's possible to position elements on a page in a specific spot using style sheets. After they're positioned, you can move them around the page using JavaScript.

Here's a really simple script that keeps the menu out from under the mouse. It's not very useful if you actually want to use the links on the menu, but it's fun to play with.

Here's the source code for the page, which is shown in Figure:

Input

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>DHTML Test</title>
<script language="JavaScript">
function flee(menu)
{
  menu.style.left = ((Math.random() * 80) + 10) + '%';
  menu.style.top = ((Math.random() * 80) + 10) + '%';
}
</script>

<style type="text/css">
  #menu
  {
    font-family: Verdana, sans-serif;
    padding: 10px;
    border: 1px solid black;
    background-color: #ffc;
    width: 150px;
    position: absolute;
    top: 40%;
    left: 40%;
  }
</style>
</head>
<body>
<div onmouseover="flee(this);" id="menu"><b>Links</b><br />
<a href="http://www.yahoo.com/">Yahoo</a><br />
<a href="http://www.salon.com/">Salon</a><br />
<a href="http://www.slashdot.org/">Slashdot</a><br />
</div>
</body>
</html>

Output

4. A page with an element that moves out of the way of the user's mouse.


This page uses the same <div> and style sheet that we've used in the past few examples. In this case, though, the onmouseover event handler associated with the <div> calls the flee() function. We pass in a reference to the <div> and the function automatically sets the position of the <div> to a random location on the page.

Creating a DHTML Pull-Down Menu

Let's look at a common application of DHTML that you'll see on many websites: a pulldown menu implemented in Dynamic HTML. The menu that we've used in the past few examples makes yet another appearance here. In this case, we've created a navigation bar across the top of the page. When the user puts the mouse pointer over the button in the navigation bar, the menu appears (and the button is highlighted). As long as the mouse pointer is over the button or the menu, the menu is displayed. Once the user removes the pointer, the menu will disappear after a 1-second delay. The page also contains some text to show that the menu does not disrupt the page layout. This page illustrates how to create a dynamic HTML interface, and shows just how many event handlers and functions are required to do so. One of the other puzzles is how to make sure that the menu appears in the correct position. Before I explain how it all works, here's the source code:

Input

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>DHTML Test</title>
<script language="JavaScript">
function highlightAndPersist(button)
{
  button.style.backgroundColor = '#ffc';
  persist();
}
function unhighlight(button)
{
  button.style.backgroundColor = '#ccf';
}

function persist()
{
  var menu = document.getElementById('menu');
  var button = document.getElementById('linkbutton');
  menu.style.position = 'absolute';
  menu.style.top = (button.offsetTop + button.offsetHeight) + 'px';
  menu.style.left = (button.offsetLeft) + 'px';
  menu.style.visibility = 'visible';
}

function hideSoon()
{
  setTimeout("hide()", 1000);
}

function hide()
{
  var menu = document.getElementById("menu");
  menu.style.visibility = "hidden";
}
</script>

<style type="text/css">
  body { margin: 0px; }
  #menu
  {
    font-family: Verdana, sans-serif;
    padding: 10px;
    border: 1px solid black;
    background-color: #ffc;
    width: 150px;
    visibility: hidden;
    position: absolute;
    top: 0px;
    left: 0px;
  }

  #navbar
  {
    font: 18px Verdana, sans-serif;
    width: 100%;
    height: 30px;
    background-color: #ccf;
    padding: 0px;
  }

  .button
  {
    width: 80px;
    height: 30px;
    text-align: center;
  }

  p { margin: 10px; }
</style>
</head>
<body>
<div id="navbar">
<div id="linkbutton" class="button" onmouseover="highlightAndPersist(this);"
  onmouseout="unhighlight(this);">
<b><a href="" onmouseover="persist();" onclick="return false;">Links</a></b>
</div>
</div>
<div id="menu" onmouseout="hideSoon();" onmouseover="persist();">
<a onmouseover="persist();" href="http://www.yahoo.com/">Yahoo</a><br />
<a onmouseover="persist();" href="http://www.salon.com/">Salon</a><br />
<a onmouseover="persist();" href="http://www.slashdot.org/">Slashdot</a><br />
</div>

<p>
Friends, Romans, countrymen, lend me your ears;<br />
I come to bury Caesar, not to praise him.<br />
The evil that men do lives after them;<br />
The good is oft interred with their bones;<br />
So let it be with Caesar. The noble Brutus<br />
Hath told you Caesar was ambitious:<br />
If it were so, it was a grievous fault,<br />
And grievously hath Caesar answer'd it.<br />
Here, under leave of Brutus and the rest--<br />
For Brutus is an honourable man;<br />
So are they all, all honourable men--<br />
Come I to speak in Caesar's funeral.<br />
</p>

</body>
</html>

Figure shows what the pop-up menu looks like when it appears.

Output

5. A pull-down menu implemented using DHTML.


Take a look at the style sheet first. Many of the rules are required to make the page look right. I also set up specific styles for the navigation bar and buttons on the navigation bar. The style applied to the menu sets its absolute position to the upper-left corner of the page, but it's also set as invisible. We'll take care of positioning it with JavaScript a bit later.

Looking at the body of the page, you can see all the event handlers we use. The <div> with the ID linkbutton is the actual button that causes the menu to appear. It has two event handlers associated with it: onmouseover and onmouseout. When the pointer is moved over it, the highlightAndPersist() function is called, and when the mouse moves away, unhighlight() is called. The highlightAndPersist() function highlights the button in the navigation bar and displays the menu. The unhighlight() function turns off the button highlighting without hiding the menu.

The link itself that's inside the button also has two event handlers: onmouseover and onclick. The onclick is just used to turn off the link so the user doesn't navigate away without seeing the menu. If you wanted to set up the page so that users who don't have browsers that support DHTML can still benefit from the navigation bar, you could take out the onclick handler and put the URL for the links page in the link. The onmouseover event handler calls persist(), which displays the menu.

The <div> containing the menu also has two event handlers: onmouseout and onmouseover. The onmouseout handler calls hideSoon(), which waits 1 second and then hides the menu. The onmouseover handler calls persist(), which displays the menu. This ensures that the menu stays open as long as the mouse is over the menu. Finally, each of the links in the menu also has an onmouseover handler that calls persist() so that the menu stays open when the user moves his mouse over the links themselves.

Now let's look at the JavaScript code. You've already seen most of this stuff; it has just been put together in a different way. The persist() function is in charge of positioning and displaying the menu. First, I grab two referencesone to the menu and the other to the menu button. Were there multiple menus, this function would take the IDs of the button and menu as parameters. Once I have the references I need, it's time to display the menu. I set the position property to absolute, just in case. Then I set the top and left properties of the menu based on the position of the button associated with the menu:

menu.style.top = (button.offsetTop + button.offsetHeight) + 'px';
menu.style.left = (button.offsetLeft) + 'px';

The offsetTop, offsetLeft, and offsetHeight properties are available for any visual element on a page. I determine where to put the top of the menu by adding the height of the button to the top position of the menu. That places it immediately under the button. The left side of the menu should line up with the left side of the button, so I just used offsetLeft for the left position of the menu.

The other functions are less interesting. The highlightAndPersist() function just changes the background color of the button and calls persist(). The unhighlight() function just changes the background color of the button back to what it was. The hide() function sets the visibility of the menu back to hidden. There's a bit more going on in hideSoon(). It uses the setTimeout() function to wait 1,000 milliseconds (one second) and then call the hide() function. This improves the usability of the page a bit by giving the user a chance to see the menu even if he mouses out of it by mistake.

Continuing Your DHTML Education

I encourage you to visit both the Microsoft and Netscape websites devoted to DHTML. Each offers an interesting perspective.

The Microsoft website has a ton of great information for using HTML and DHTML with Internet Explorer:

http://msdn.microsoft.com/workshop/author/dhtml/dhtml_node_entry.asp

Netscape appears to be leading the cross-browser compatibility charge and has extensive articles and technical notes at http://devedge.netscape.com/. You might also find http://www.mozilla.org/docs/dom/ interesting.

Other sites that have useful information include the following:




 Python   SQL   Java   php   Perl 
 game development   web development   internet   *nix   graphics   hardware 
 telecommunications   C++ 
 Flash   Active Directory   Windows