原文地址:How to reach what we want to change
For the inexperienced Javascript developers,
HTML is their
playground.
- <a href="index.html"
-
onmouseover="image1.src='1on.gif'"
-
onmouseout="image1.src='1off.gif'">
-
<img src="1off.gif" name="image1" border="0" height="150" width="150"
-
alt="home"></a>
or if they are a bit more advanced:
- <a href="index.html"
-
onmouseover="roll('home',1)"
-
onmouseout="roll('home',0)">
-
<img src="home.gif" name="home" border="0"
-
height="150" width="150"
-
alt="home"></a>
- // preloading image
-
homeoff = new Image();
-
homeoff.src = 'home.gif';
-
homeon = new Image();
-
homeon.src = 'homeoff.gif';
-
function roll(imgName,a)
-
{
-
imgState=a==0?eval(imgName + 'on.src'):eval(imgName + 'off.src');
-
document.images[imgName].src = imgState;
-
}
In any case, all the event calls are in the
HTML, and if the function
name changes, we'd have to change each document. Furthermore, each rollover means
a lot of markup which adds to the overall page weight.
Out! Out! - you demons of inline event calls
Let's forget for the moment, that almost every rollover effect these days can
be achieved via CSS rather
than Javascript - let's say we want to use the following markup and create a
rollover for the image:
HTML:
- <a href="index.html"><img src="home.gif" id="home" alt="home"></a>
Now, how to change that when the mouse is over it?
Climbing the branches of the node tree
Each XML (and that
includes HTML)
document is a node tree. A node is a part of this tree (think of a
file or a folder in windows explorer when you navigate around your harddisk). A
node can be [1] - for HTML,
only three are really interesting: element, TextNode and
AttributeNode.
Our climbing equipment
Let's see which functions and attributes we can use to navigate the
node tree of a document, and how to jump from one element to another.
Functions to reach an element in the page
- getElementById('elementID')
-
returns the element with the id elementID as an object.
-
getElementsByTagName('tag')
-
returns all elements with the name tag as an array.
Of course you can mix and match these two. Some examples:
- document.getElementById('navigation').getElementsByTagName('a')[3];
-
returns the fourth link inside the element with the ID 'navigation'
-
document.getElementsByTagName('div')[2].getElementsByTagName('p')[0];
-
returns the first paragraph inside the third div in the document.
Tools to navigate from a certain element
- childNodes
-
returns an array of all the nodes inside the current one. There is also firstChild and lastChild, which are shorter versions for childNodes[0] and childNodes[this.childNodes.length-1].
-
parentNode
-
The element containing this one
-
nextSibling
-
the next element on the same level in the document tree
-
previousSibling
-
the previous element on the same level in the document tree
All of these can be mixed at will and need.
- var other=document.getElementById('nav').childNodes[3].firstChild;
returns the 4th element's first sub element inside the element
with the ID nav.
- var prevlink=o.parentNode.previousSibling.firstChild.childnodes[2];
returns the third node inside the previous element
that is on the same level as the parent element of o.
Attributes and functions for elements
- attributes
-
returns an array of all the attributes of this element. Does not work with Internet Explorer below version 6.
-
data
-
returns or sets the textual data of the node
-
nodeName
-
returns the name of the node (the HTML element name)
-
nodeType
-
returns the type of the node — 1 is an element node, 2 attribute and 3 text.
-
nodeValue
-
returns or sets the value of the node. This value is the text when the node is a textnode, the attribute if it is an attribute or null if it is an element.
-
getAttribute(attribute)
-
returns the value of the attribute attribute.
- var other=document.getElementById('nav').firstChild;
-
if(other.nodeType==3)
-
{
-
other.data='newtext';
-
}
-
if(other.nodeType==1)
-
{
-
other.firstChild.data='newtext';
-
}
Now to reach the image in our example, we can use either
getElementsByTagName or getElementById.
- <a href="index.html"><img src="home.gif" id="home" alt="home"></a>
- function findimg()
-
{
-
var image;
-
image=document.getElementById('home');
-
if (image)
-
{
-
image.style.border='3px dashed #ccc';
-
}
-
}
or:
- function findimg()
-
{
-
var imgs,i;
-
imgs=document.getElementsByTagName('img');
-
for(i in imgs)
-
{
-
if(/home.gif/.test(imgs[i].src))
-
{
-
imgs[i].style.border='3px dashed #ccc';
-
}
-
}
-
}
Using getElementById is a lot easier, as we don't have to loop
through all elements and find a unique identifier. In this example, we checked
if the src attribute of the image object contains 'home.gif'. A more common
way is to check for a special class.
HTML:
- <a href="index.html"><img src="home.gif" class="roll" alt="home"></a>
Javascript:
- function findimg()
-
{
-
var imgs,i;
-
imgs=document.getElementsByTagName('img');
-
for(i in imgs)
-
{
-
if(/roll/.test(imgs[i].className))
-
{
-
imgs[i].style.border='3px dashed #ccc';
-
}
-
}
-
}
Now, to add a roll-over effect, all we need to do is to add a function that
does the switching of the image source, and adds the event handlers to the image.
- function findimg()
-
{
-
var imgs,i;
-
// loop through all images of the document
-
imgs=document.getElementsByTagName('img');
-
for(i=0;i<imgs.length;i++)
-
{
-
// test if the class 'roll' exists
-
if(/roll/.test(imgs[i].className))
-
{
-
// add the function roll to the image onmouseover and onmouseout and send
-
// the image itself as an object
-
imgs[i].onmouseover=function(){roll(this);};
-
imgs[i].onmouseout=function(){roll(this);};
-
}
-
}
-
}
-
function roll(o)
-
{
-
var src,ftype,newsrc;
-
// get the src of the image, and find out the file extension
-
src = o.src;
-
ftype = src.substring(src.lastIndexOf('.'), src.length);
-
// check if the src already has an _on and delete it, if that is the case
-
if(/_on/.test(src))
-
{
-
newsrc = src.replace('_on','');
-
}else{
-
// else, add the _on to the src
-
newsrc = src.replace(ftype, '_on'+ftype);
-
}
-
o.src=newsrc;
-
}
-
window.onload=function(){
-
findimg();
-
}
Good for the moment, but we forgot one thing: Albeit being merely eye candy, a
rollover should work without a mouse, too. To achieve this, we need to check
if the link around the image gets the focus or not, as the image itself is not
reachable via the keyboard when embedded in a link.
To do this, we need to get the element that contains the image, in this case
the link. We do this via parentNode command. As this also changes
the object that gets sent as a parameter to the function roll(),
we need to find the image again. Hence we loop through the childNodes of the
link and check which one is an element and an image by checking nodeType
and nodeName. This is necessary, as some browsers see whitespace in
the source as an own node, whereas others don't.
- function findimg()
-
{
-
var imgs,i;
-
// Loop through all images, check if they contain the class roll
-
imgs=document.getElementsByTagName('img');
-
for(i=0;i<imgs.length;i++)
-
{
-
if(/roll/.test(imgs[i].className))
-
{
-
// add the function roll to the parent Element of the image
-
imgs[i].parentNode.onmouseover=function(){roll(this);};
-
imgs[i].parentNode.onmouseout=function(){roll(this);};
-
imgs[i].parentNode.onfocus=function(){roll(this);};
-
imgs[i].parentNode.onblur=function(){roll(this);};
-
}
-
}
-
}
-
function roll(o)
-
{
-
var i,isnode,src,ftype,newsrc,nownode;
-
// loop through all childNodes
-
for (i=0;i<o.childNodes.length;i++)
-
{
-
nownode=o.childNodes[i];
-
// if the node is an element and an IMG set the variable and exit the loop
-
if(nownode.nodeType==1 && /img/i.test(nownode.nodeName))
-
{
-
isnode=i;
-
break;
-
}
-
}
-
// check src and do the rollover
-
src = o.childNodes[isnode].src;
-
ftype = src.substring(src.lastIndexOf('.'), src.length);
-
if(/_on/.test(src))
-
{
-
newsrc = src.replace('_on','');
-
}else{
-
newsrc = src.replace(ftype, '_on'+ftype);
-
}
-
o.childNodes[isnode].src=newsrc;
-
}
-
-
window.onload=function(){
-
findimg();
-
}
Why don't you try it?
Simply
and try one of the following tasks. Follow the solution links to see
one possible solution. The solutions have the Javascript inline as a
demonstration, not in an extra document where they should be. This was
done to
help you see the necessary markup in one document rather than two.
- Change the colour of every H2 headline to blue.
- Outline every second paragraph with a black border.
- Check which of the links in the document is external
(by checking that the href attribute does not contain window.location.hostname)
and add the href of the link as a text in parenthesis after the link.
Until you learn how to do that propely, use the
innerHTML attribute of the link object to change
its content.
- Add an onclick handler to each link
with the attribute target that opens a 400x400 pixels pop-up window.
Links
阅读(915) | 评论(0) | 转发(0) |