Chinaunix首页 | 论坛 | 博客
  • 博客访问: 333111
  • 博文数量: 104
  • 博客积分: 2815
  • 博客等级: 少校
  • 技术积分: 595
  • 用 户 组: 普通用户
  • 注册时间: 2010-05-06 16:32
文章分类

全部博文(104)

文章存档

2013年(1)

2012年(2)

2011年(21)

2010年(80)

我的朋友

分类: 系统运维

2011-09-14 22:26:19

原文地址:
How to reach what we want to change

For the inexperienced Javascript developers, HTML is their playground.

  1. <a href="index.html"
  2. onmouseover="image1.src='1on.gif'"
  3. onmouseout="image1.src='1off.gif'">
  4. <img src="1off.gif" name="image1" border="0" height="150" width="150"
  5. alt="home"></a>

or if they are a bit more advanced:

  1. <a href="index.html"
  2. onmouseover="roll('home',1)"
  3. onmouseout="roll('home',0)">
  4. <img src="home.gif" name="home" border="0"
  5. height="150" width="150"
  6. alt="home"></a>
  1. // preloading image
  2. homeoff = new Image();
  3. homeoff.src = 'home.gif';
  4. homeon = new Image();
  5. homeon.src = 'homeoff.gif';
  6. function roll(imgName,a)
  7. {
  8.  imgState=a==0?eval(imgName + 'on.src'):eval(imgName + 'off.src');
  9.  document.images[imgName].src = imgState;
  10. }

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:
  1. <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
  1. getElementById('elementID')
  2.     returns the element with the id elementID as an object.
  3. getElementsByTagName('tag')
  4.     returns all elements with the name tag as an array.

Of course you can mix and match these two. Some examples:

  1. document.getElementById('navigation').getElementsByTagName('a')[3];
  2.     returns the fourth link inside the element with the ID 'navigation'
  3. document.getElementsByTagName('div')[2].getElementsByTagName('p')[0];
  4.     returns the first paragraph inside the third div in the document.
Tools to navigate from a certain element
  1. childNodes
  2.     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].
  3. parentNode
  4.     The element containing this one
  5. nextSibling
  6.     the next element on the same level in the document tree
  7. previousSibling
  8.     the previous element on the same level in the document tree

All of these can be mixed at will and need.

  1. var other=document.getElementById('nav').childNodes[3].firstChild;
returns the 4th element's first sub element inside the element with the ID nav.
  1. 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
  1. attributes
  2.     returns an array of all the attributes of this element. Does not work with Internet Explorer below version 6.
  3. data
  4.     returns or sets the textual data of the node
  5. nodeName
  6.     returns the name of the node (the HTML element name)
  7. nodeType
  8.     returns the type of the node — 1 is an element node, 2 attribute and 3 text.
  9. nodeValue
  10.     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.
  11. getAttribute(attribute)
  12.     returns the value of the attribute attribute.
  1. var other=document.getElementById('nav').firstChild;
  2. if(other.nodeType==3)
  3. {
  4.  other.data='newtext';
  5. }
  6. if(other.nodeType==1)
  7. {
  8.  other.firstChild.data='newtext';
  9. }

Now to reach the image in our example, we can use either getElementsByTagName or getElementById.

  1. <a href="index.html"><img src="home.gif" id="home" alt="home"></a>
  1. function findimg()
  2. {
  3.  var image;
  4.  image=document.getElementById('home');
  5.  if (image)
  6.   {
  7.    image.style.border='3px dashed #ccc';
  8.   }
  9. }
or:
  1. function findimg()
  2. {
  3.  var imgs,i;
  4.  imgs=document.getElementsByTagName('img');
  5.  for(i in imgs)
  6.  {
  7.   if(/home.gif/.test(imgs[i].src))
  8.    {
  9.     imgs[i].style.border='3px dashed #ccc';
  10.    }
  11.   }
  12. }

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:
  1. <a href="index.html"><img src="home.gif" class="roll" alt="home"></a>
Javascript:
  1. function findimg()
  2. {
  3.  var imgs,i;
  4.  imgs=document.getElementsByTagName('img');
  5.  for(i in imgs)
  6.   {
  7.   if(/roll/.test(imgs[i].className))
  8.    {
  9.     imgs[i].style.border='3px dashed #ccc';
  10.    }
  11.   }
  12. }

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.

  1. function findimg()
  2. {
  3.  var imgs,i;
  4. // loop through all images of the document
  5.  imgs=document.getElementsByTagName('img');
  6.  for(i=0;i<imgs.length;i++)
  7.  {
  8. // test if the class 'roll' exists
  9.   if(/roll/.test(imgs[i].className))
  10.   {
  11. // add the function roll to the image onmouseover and onmouseout and send
  12. // the image itself as an object
  13.    imgs[i].onmouseover=function(){roll(this);};
  14.    imgs[i].onmouseout=function(){roll(this);};
  15.   }
  16.  }
  17. }
  18. function roll(o)
  19. {
  20.  var src,ftype,newsrc;
  21. // get the src of the image, and find out the file extension
  22.  src = o.src;
  23.  ftype = src.substring(src.lastIndexOf('.'), src.length);
  24. // check if the src already has an _on and delete it, if that is the case
  25.  if(/_on/.test(src))
  26.  {
  27.   newsrc = src.replace('_on','');
  28.  }else{
  29. // else, add the _on to the src
  30.   newsrc = src.replace(ftype, '_on'+ftype);
  31.  }
  32.  o.src=newsrc;
  33. }
  34. window.onload=function(){
  35.  findimg();
  36. }

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.

  1. function findimg()
  2. {
  3.  var imgs,i;
  4. // Loop through all images, check if they contain the class roll
  5.  imgs=document.getElementsByTagName('img');
  6.  for(i=0;i<imgs.length;i++)
  7.  {
  8.   if(/roll/.test(imgs[i].className))
  9.   {
  10. // add the function roll to the parent Element of the image
  11.   imgs[i].parentNode.onmouseover=function(){roll(this);};
  12.   imgs[i].parentNode.onmouseout=function(){roll(this);};
  13.   imgs[i].parentNode.onfocus=function(){roll(this);};
  14.   imgs[i].parentNode.onblur=function(){roll(this);};
  15.   }
  16.  }
  17. }
  18. function roll(o)
  19. {
  20.  var i,isnode,src,ftype,newsrc,nownode;
  21. // loop through all childNodes
  22.  for (i=0;i<o.childNodes.length;i++)
  23.  {
  24.   nownode=o.childNodes[i];
  25. // if the node is an element and an IMG set the variable and exit the loop
  26.   if(nownode.nodeType==1 && /img/i.test(nownode.nodeName))
  27.   {
  28.    isnode=i;
  29.    break;
  30.   }
  31.  }
  32. // check src and do the rollover
  33.  src = o.childNodes[isnode].src;
  34.  ftype = src.substring(src.lastIndexOf('.'), src.length);
  35.  if(/_on/.test(src))
  36.  {
  37.   newsrc = src.replace('_on','');
  38.  }else{
  39.   newsrc = src.replace(ftype, '_on'+ftype);
  40.  }
  41.  o.childNodes[isnode].src=newsrc;
  42. }

  43. window.onload=function(){
  44.  findimg();
  45. }
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.

  1. Change the colour of every H2 headline to blue.
  2. Outline every second paragraph with a black border.
  3. 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.
  4. Add an onclick handler to each link with the attribute target that opens a 400x400 pixels pop-up window.
Links
  • [1] Node types:
阅读(894) | 评论(0) | 转发(0) |
0

上一篇:JSP tag 学习

下一篇:rxvt-unicode 黑底绿字

给主人留下些什么吧!~~