鼠标点击控制

这一节我们将告诉你如何运用鼠标来控制这些运动方. 请你记住我们的目标是写出兼容在 NetScape 和 Internet Explore 上的程序。

鼠标点击控制

跟键盘控制一样,我们可以用鼠标来控制任何动画效果。下面我们将要设立一个连接,当拿鼠标按这个连接的时候, 元素就能滑动, 当你放开鼠标的时候,滑动 就停止了。程序几乎跟键盘控制的一样。

  function init() {
	if (ns4) block = document.blockDiv
	if (ie4) block = blockDiv.style
	block.xpos = parseInt(block.left)
	block.active = false
  }

  function slide() {
	if (block.active) {
		block.xpos += 5
		block.left = block.xpos
		setTimeout("slide()",30)
	}
  }

区别在于如何做这个连接, 请看下面的语句:

 <A HREF="javascript:void(null)" onMouseDown="block.active=true;
 slide(); return false;" 
	onMouseUp="block.active=false" onMouseOut="block.active=false">move</A>

这里解释一下上面的连接:

  • HREF="javascript:void(null)" 告诉浏览器不要换网页。 我们也可以用 HREF="#"
    来达到这个目的.
  • onMouseDown 把变量 block.active 设为 true, 然后启动 slide()滑动元素。
  • onMouseUp 把变量 block.active 设为 false, 这样滑动就停止了。
  • onMouseOut 把变量 block.active 设为 false, 这样滑动就停止了。

 

看这个范例

可视区的调整

这一节我们将告诉你如何来控制一个元素的可视区, 也就是说用这个技术 来展开或缩小一个元素的可视区域. 请你记住了我们的目标是写出兼容在NetScape 和 Internet Explore 上的程序

Clipping Layers

Clipping 的意思就是决定元素的哪个部位可以被看到. 就像一个模子一样.它不会改变任何元素的性质. Clipping 的区域是一个长方形. 而这个长方形的尺寸取决于于四个边的位置. 这四个边用 top, right, botton, left 来表示. 请 注意这四个边的位置是相对于元素的而不是相对于窗口的.

Clipping 的 CSS 语法是

  clip:rect(top,right,bottom,left)

这里 top, right, bottom, left 的值全是 pixels. 注意它们的位置是固定的. 下面 的 DIV 元素就被 Clipping 来重新确定了可视范围.

<DIV ID="blockDiv" STYLE="position:absolute; left:50; 
	top:80; width:100; height:70; clip:rect(-15, 15, 85, 85); 
	background-color:#FF0000; 
	layer-background-color:#FF0000;">
</DIV>
在上面这个例子中,
  • 上边可视区域比原来扩大 15 格, 因为 top = -15
  • 右边可视区域比原来小了 15 格, 因为 right = 15
  • 下边可视区域比原来扩大 15 格, 因为 bottom = 85, 而元素高度是 70
  • 左边可视区域比原来小了 15 格, 因为 right = 85, 而元素宽度是 100

在上面这个例子, 有两个性质需要解释一下. background-color 是专为 ie4 而 layer-background-color 是为 Netscape. 这个性质是设立 DIV 背景颜色. 一般我们不需要给出 DIV 的 height. 但如果要用 Clipping, 那你最好给.
 

你也可y以给 DIV 元素设置背景图象, background-image:URL(filename.gif) 是为IE所设, 而 layer-background-image:URL(fildname.gif). 是为 Netscape. 但 Netscape 需要另外一个性质 repeat:no. 请看下面的例子

<DIV ID="blockDiv" STYLE="position:absolute; left:50; top:80; 
	width:100; height:50; clip:rect(-10,110,60,-10); 
	background-image:URL(filename.gif); 
	layer-background-image:URL(filename.gif); repeat:no;}

JavaScript 和 Clipping

我们已经知道了用 clipping 的四个值来决定一个元素的可视区. 同改变元 素位置一样, 我们也可以用 JavaScript 来改变这四个值.

Netscape 的 Clipping:

在 Netscape, 你可以用下面这四个性质来取得 Clipping

  document.divName.clip.top
  document.divName.clip.right
  document.divName.clip.bottom
  document.divName.clip.left

比如你想要把 Clipping 的 top 显示在屏幕上, 你可以用 alert:

  alert(document.divName.clip.top)

你如果想改变 top 的值到 50 pixels, 你可以

  document.divName.clip.top = 50

Internet Explorer 的 Clipping:

IE 可以用一个性质得到所有四个 Clipping 的值, 比如

  alert(divName.style.clip)

这句的结果将是

  "rect(0px 50px 100px 0px)"

当你想改变 Clipping 的值的时候, 你也需要把这四个值一起改动. 烦!

  divName.style.clip = "rect(0px 100px 50px 0px)"

通用子程序 clipValues()

这个子程序是用来得到其中一个 Clipping 的值的.

  function clipValues(obj,which) {
    if (ns4) {
	if (which=="t") return obj.clip.top
	if (which=="r") return obj.clip.right
	if (which=="b") return obj.clip.bottom
	if (which=="l") return obj.clip.left
    }
    else if (ie4) {
	var clipv = obj.clip.split("rect(")[1].split(")")[0].split("px")
	if (which=="t") return Number(clipv[0])
	if (which=="r") return Number(clipv[1])
	if (which=="b") return Number(clipv[2])
	if (which=="l") return Number(clipv[3])
    }
  }

你只要告诉这个子程序哪个 layer 的哪条边, 它就能告诉你那条边的Clipping 的值. 假如我们给一个 Layer 设立了一个指针变量 "blockDiv", 我们就可以用下面的语句来显示 top 的 clipping 的值

  alert(clipValues(block,"t"))

这里我们用了这样的表示法 "t" (top), "r" (right), "b" (bottom), "l" (left).

看以上的范例

改变 Clip 值的通用子程序

clipTo() 子程序:

clipTo() 让你能重新 Clip 一个 Layer 到给定的值

  function clipTo(obj,t,r,b,l) {
    if (ns4) {
	obj.clip.top = t
	obj.clip.right = r
	obj.clip.bottom = b
	obj.clip.left = l
    }
    else if (ie4) obj.clip = "rect("+t+"px "+r+"px "+b+"px "+l+"px)"
  }

用它的时候, 你要给出 Layer 的名字和四个边的 Clip 的值, 比如

  clipTo(block,0,100,100,0)

clipBy() 子程序:

clipBy() 可以让你相对于当前的 Clip 区域增减 Clip 的四个边

  function clipBy(obj,t,r,b,l) {
    if (ns4) {
	obj.clip.top = clipValues(obj,'t') + t
	obj.clip.right = clipValues(obj,'r') + r
	obj.clip.bottom = clipValues(obj,'b') + b
	obj.clip.left = clipValues(obj,'l') + l
    }
    else if (ie4) 
	obj.clip = "rect("+(this.clipValues(obj,'t')+t)+
	"px "+(this.clipValues(obj,'r')+r)+"px "
	+Number(this.clipValues(obj,'b')+b)+"px "
	+Number(this.clipValues(obj,'l')+l)+"px)"
  }

比如你想稍微增大 right 和 bottom 边的值, 你可以

  clipBy(block,0,10,5,0)

看以上范例

动画 Clipping (Wiping)

所谓 wiping 就是连续相对改变 clipping 区域. 下面这个子程序就是往右边
逐步扩大 clipping 区域, 每次 5 pixels.

  function wipe1() {
    clipBy(block,0,5,0,0)
    setTimeout("wipe1()",30)
  }

我们还得加上个条件来停止 wiping,

  function wipe1() {
    if (clipValues(block,'r')<200) {
	clipBy(block,0,5,0,0)
	setTimeout("wipe1()",30)
    }
  }

看以上范例

叠套层次

这一节我们将告诉你怎样层次里面套层次 (nesting layers).

叠套层次

元素, 层次, Layer 这三个词是我们在教程经常用的. 它们是一个意 思: 就是一段在 <DIV> 里的 HTML. 而所谓叠套层次就是层次里面 套层次, 或是 netsting layers.

我们把在一个层次里的层次叫子层次, 而把包括子层次的层次叫主 层次. 子层次的位置全是相对于主层次的. 打个比喻, 主层次对子层 次的关系就像窗口对主层次的关系.

我们以后会发觉叠套层次会给我们带来一些方便. 这是因为子层次 的位置是相对于主层次的. 也就是说当我们移动主层次的时候, 子 层次也随着移动.

用 JavaScript 来实现层次套层次在 NetScapt 和 Internet Explorer 是大 不相同. 这就是为什么我们很少看到层次套层次的例子. 这里我们 将要提供一个方法去实现兼容的层次重叠.

Stylesheets 和叠套

叠套层次其实就是把子层次 DIV 写在主层次 DIV 的里面.

<DIV ID="parent1Div">
	<DIV ID="child1Div"></DIV>
	<DIV ID="child2Div"></DIV>
	
</DIV>

对于叠套层次, 在 DIV 里面定义 STYLE 是无法工作的, 所以我们只 能用 <STYLE> 来定义叠套层次的性质.

<STYLE TYPE="text/css">
<!--
#parent1Div {position:absolute; left:100; top:80; width:500; height:347; 
		clip:rect(0,500,347,0); 
		background-color:#C0C0C0; layer-background-color:#C0C0C0;}
#child1Div {position:absolute; left:-20; top:200; width:70; height:70; 
		clip:rect(0,70,70,0); 
		background-color:#FF0000; layer-background-color:#FF0000;}
#child2Div {position:absolute; left:100; top:280; width:300; height:60; 
		clip:rect(0,300,60,0); 
		background-color:#CCFFCC; layer-background-color:#CCFFCC;}
-->
</STYLE>

<DIV ID="parent1Div">
	<IMG src="../picture/bj01_tiantan.jpg" border=0>
	<DIV ID="child1Div"></DIV>
	<DIV ID="child2Div"><center>北京天坛祈年殿</center></DIV>
</DIV>

点这里看上面的例子.

在上面的例子里我们还定义了可视区. 一般来说你应该定义可视区和颜色. 我们这个例子里, 主层次是示例图片, 第一个子层次是个红色方形, 第二个子层次是绿色长方形, 上有照片说明.

JavaScript 和叠套

JavaScrip 在 Netscape 和 Internet Explore 里操纵叠套是大不一样的. 在 IE 里处理叠套层次和处理一般层次没有什么区别.

  childLayer.style.properyName

但是对 Netscape 来说, 如果你想操纵子层次你必须参照它的主层次.

  document.parentLayer.document.childLayer.propertyName

这里的在 layer 名字之前的 document 是因为 Netscape 把 layer 看做document. 另外你所要知道的是叠套的层次是没有限制的, 也就是说 你可以叠套无数层. 比如我们把上面的例子里的第二个子层次放到 第一个子层次里.

<DIV ID="parent1Div">
  <DIV ID="child1Div">
	<DIV ID="child2Div"></DIV>
  </DIV>
</DIV>

在这个情况下, 想要操纵 child2Div, 你得

  document.parent1Div.document.child1Div.document.child2Div.propertyName

我们现在可以来为这些层次定义指针变量

function init() {
  if (ns4) {
	parent1 = document.parent1Div
	child1 = document.parent1Div.document.child1Div
	child2 = document.parent1Div.document.child2Div
  }
  if (ie4) {
	parent1 = parent1Div.style
	child1 = child1Div.style
	child2 = child2Div.style
  }
}

但我们还要处理一些其他的问题.

IE 的麻烦和处理:

当你用 STYLE tag 来定义你的 Layer 的时候, IE 居然让你读不出来 Layer 性质的初始值. 比如你想知道 parent1 刚开始的位置:

 alert(parent1.left)

在 IE 里你将什么也得不到. 但当你用 JavaScript 改变了这些性质的 值以后, 你就能看到它们的值了. 这个问题显然使得我们无法知道 元素的初始位置, 也就是说无法去准确的控制它了. 但 Microsoft 添 加了一些非标准 CSS 性质在 IE4 里可以使得我们能解决这个麻烦.

  • pixelLeft
  • pixelTop
  • pixelWidth
  • pixelHeight

在 IE4 里, 这几个新的性质不会受到 STYLE tag 的影响. 所以我们可 把程序做如下的修改使得我们能记住初始位置.

function init() {
  if (ns4) {
	parent1 = document.parent1Div
	parent1.xpos = parent1.left
	parent1.ypos = parent1.top
	child1 = document.parent1Div.document.child1Div
	child1.xpos = child1.left
	child1.ypos = child1.top
	child2 = document.parent1Div.document.child2Div
	child2.xpos = child2.left
	child2.ypos = child2.top
  }
  if (ie4) {
	parent1 = parent1Div.style
	parent1.xpos = parent1.pixelLeft
	parent1.ypos = parent1.pixelTop
	child1 = child1Div.style
	child1.xpos = child1.pixelLeft
	child1.ypos = child1.pixelTop
	child2 = child2Div.style
	child2.xpos = child2.pixelLeft
	child2.ypos = child2.pixelTop
  }
}

这样你就可以像以前那样很方便的改变 layer 的位置了.

点这里 看移动主层次和子层次的范例.

可视性质和叠套:

如果你忘记了给出子层次的可视性质, 它将会使用主层次的可视性质.

点这里 看可视性质和叠套层次的关系.

NS和IE的区别

相同点
两者都支持静态 CSS
所谓静态CSS就是只能读不能改。虽然两者支持的程度不一样但大部分基本的CSS性质都得到支持

两者都支持CSS-P或是说绝对和相对定位。

两者都支持动态定位
动态定位包含物体位置的改动,物体前后词序的改动,隐蔽 和显示, 剪接区域(clipping area)

两者都支持动态HTML内容变化
你如果用的是NS, 你可以用layer的document.write来更换 layer里的内容, 比如

document.layername.document.write("<H1>新内容</H1>");
document.layername.document.close();


你如果用的是IE, 下面的语句可以帮你改变物体的内容。

layername.innerHTML = 新的 HTML 内容
layername.innerText = 新内容

两者都支持 event, 比如onClick, onMouseOver 等等。

不相同地方
IE 可以改变CSS的性质而NS却不行。
IE用style来改变元素的性质,比如

elementname.style.color="#FF0000";

NS可以loading文件到元素中,而IE却不能
document.elementname.src="external.htm";

IE支持平行的DOM,而NS支持树形的DOM
请看下面的例子来观察两者的区别。如果一个可放置的物体 被包含在另外一个可放置的物体之内,那么IE可用如下的方法 来读物体的性质

document.all.block1.style.visibility="hidden";
document.all.block2.style.posLeft=20;


而NS的方法就稍有不同

document.block1.visibility="hidden";
document.block1.document.block2.left=20;

 

变换层次中的内容

当你用 <DIV> 设立一个层次以后, 你可以把它放到屏幕上的任何一个地方。 但有没有办法更换里面的内容呢? 这一节就是介绍如何更换层次里面的内容。

Internet Explorer 4.0:

用 Explorer 很容易实现层次内容的更换。下面的语句就可以让你随意的更换层次里的内容。

  document.all.divID.innerHTML = "任何HTML或文字"

这个语句中的 divID 是你想要更换内容的 DIV 的 ID。 另外,你可以用另一种方法实现同样的功能

  document.all["divID"].innerHTML = "任何HTML或文字"

而第二种方法更方便于我们写通用的网页。

Netscape Navigator 4.0:

用 Netscape 就稍微麻烦点。 每个层次在 Netscape 里本身就是一个document. 所以可用 document.write() 命令就能把你想要写的东西写到层次里。 但注意要用 document.open() 和 document.close() 打开和关闭层次。比如往网页里写东西

  document.open()
  document.write("my text here")
  document.close()

如果要往层次里写东西,要加上层次的 ID

  document.layers["divID"].document.open()
  document.layers["divID"].document.write("my text here")
  document.layers["divID"].document.close()

通用程序

把上面所讨论的合在一起,我们可以写出一个通用的改换内容的子程序

function layerWrite(id,nestref,text) {
  if (ns4) {
    var lyr;
   
    if (nestref) {
      lyr = eval('document.'+nestref+'.document.'+id+'.document')
    else
      document.layers[id].document

    lyr.open()
    lyr.write(text)
    lyr.close()
  }
  else if (ie4) {
    document.all[id].innerHTML = text
  }
}

在你的网页里用这个子程序就可以更换内容。

  layerWrite("mylayer",null,"my text here")

请点 这里 看更换层次内容的例子

自动产生菜单


用 JavaScript 来产生菜单可给你省很多事。比如你有好几个网页 但都用一样的菜单。另外改动的时候也很方便。只要改一个地方就 行了。

这个教程另外一个目的是给你展示如何运用数组和如何用JavaScript 来产生HTML。
 

数组


JavaScript 的数组很灵活,你可用下面的命令产生它

var yourArray = new Array();

这个数组是可以任意扩张的。 也就是说, 它里面的元素可以随时 添加。 比如

yourArray[0] = "first element";

其他的 JavaScript code

yourArray[1] = "second element"

你可注意到数组的第一个元素从零开始。这个规则和 C 里面的数组 一样。当你想要知道到底有多少元素在这个数组里的时候,你可以用
yourArray.length
 

document.writeln


document.writeln() 是用来把字串写到网页上。但它另外一个很 重要的功能是它可以动态的产生HTML。请看下面的原码

document.writeln("<H1>DHTML Builder</H>");

就是把一个题目写在网页上。 你可能觉得干吗不直接写就行了呢。 用JavaScript来写HTML的优点是你可以动态的来产生HTML。
 

菜单原码


下面就是自动产生菜单的原码。你可把它拷贝到一个文件中比如

menubar.js

然后修改menuName 和 menuUrl 数组里的元素内容根据你自己的 需要。你可以增加或减少元素。

你如果要改底色,只要修改 bgcolor 就行了。 而宽度可以用 width 来改变。

在你调用他的时候,只要写下面的语句就行了

<SCRIPT src="menubar.js"></SCRIPT>
<SCRIPT>createMenuBar("DHTML Home");</SCRIPT>
 

 


// Background color of menu bar
var bgcolor = "#FFFFCC"
var width = 500

// Link names
var menuName = new Array();
menuName[0] = "DHTML Home";
menuName[1] = "Book";
menuName[2] = "Daily";
menuName[3] = "Emacs";
menuName[4] = "Photoshop";

// Links
var menuUrl = new Array();
menuUrl[0] = "index.html";
menuUrl[1] = "book.html";
menuUrl[2] = "daily.html";
menuUrl[3] = "emacs.html";
menuUrl[4] = "photoshop.html";

// Produce menu bar
function createMenuBar(pageName) {
document.writeln("<style> H3 {font-size:16pt} </style>");
document.writeln("<TABLE BORDER=0 CELLPADDING=0 CELLSPACING=0 WIDTH=" + width + ">");
document.writeln("<tr><td bgcolor=#669900>");
document.writeln("<table border=0 cellspacing=1 cellpadding=1 width=100% ");
document.writeln("bgcolor=" + bgcolor + "><TR>");
for (i = 0; i < menuName.length; i++) {
if (pageName == menuName[i]) {
document.writeln(" <TD align=center><FONT color=FF9900><B>");
document.writeln(menuName[i] + "</B></FONT></TD>");
}
else {
document.writeln("<TD align=center><a href=" + menuUrl[i] + ">"
document.writeln(menuName[i] + "</A></TD>");
}
}
document.writeln("</TR></TABLE></TD></TR></TABLE>");
}

框架的操作


这里我们主要回答两个常碰到的问题

1. 如何让你的网页从别人的框架里扩展到整个窗口
2. 如何使得你的网页进入框架机构

这里我们主要讨论大家常用的框架结构:一个左框架用做菜单一个右框架 用做内容。
 

如何让你的网页从别人的框架里扩展到整个窗口

请考虑下面这种情况:假如你的网页做为别人网页的一个连接。但当访问 者点击连接时,你的网页被展现在右边的框架中。而且你的网页也是有左 右两个框架。这时候访问者会看到三个框架。最左边是别人的菜单框架, 中间是你的菜单框架,右边是你的内容框架。

这里就告诉你如何让你的网页占据整个窗口。也就是说 break 别人网页的 框架结构。

在你的网页里你只需要检查是否你的网页在整个框架结构中的最高位置。 如果不是在最高的位置,就替换最高位置里的内容为你的网页。请把如下 的 Javascript 放到你网页中的 中。

<SCRIPT>
if (top.location != this.location) {
top.location = this.location;
}
</SCRIPT>

你如果了解DOM, 你就知道这里的 top 是指的是框架的最高层,而 this 是指的你网页所在的框架。
 

如何使得你的网页进入框架机构

跟上面的情况相反的是搜寻机找到你的一个网页但不知道它只是你网页的右边部分。这样访问者只能看到你网页的部分内容。下面的语句可以让你克服这个毛病

<SCRIPT>
if (top.location == this.location) {
top.location.href = "index.html";
}
</SCRIPT>

这里的 index.html 是你的首页。

窗口之间的控制

简介
用 JavaScript 很容易用一个窗口来控制另一个窗口中的内容。唯一的要求 是这两个窗口必须有父子关系。也就是说,一个窗口必须是由另外一个窗口 来打开的。 通过这一课,你将会

打开一个窗口
连接主窗口和子窗口
用主窗口来控制子窗口
用子窗口来控制主窗口

打开一个新窗口
你可以 JavaScript 的函数 window.open( ) 来打开一个窗口, 比如

window.open("adv04_win2.htm", "newWin1");

其中第一个参数是子窗口里的网址。第二个参数是子窗口的名字。另外你还 可以用第三个参数来定义子窗口的性质。 比如

window.open("adv04_win2.htm", "newWin1", "toolbar=no,width=700,height=500");

上面一句是打开一个宽 700 高 500 没有工具条的子窗口。

连接主窗口和子窗口
虽然你已经让主窗口打开了一个子窗口,可是它们之间谁也不认识谁。当然 也无法互相控制了。 幸运的是我们可以用 JavaScript 的变量来记住对方或 是说用变量来明确它们之间的父子关系。

现在假定我们主窗口的文件名字叫 adv04_win1.htm, 子窗口的文件名字叫 adv04_win2.htm。 在主窗口里,在打开子窗口的时候,我们用于个变量,比 如 childWin 来记住子窗口

childWin = window.open("adv04_win2.htm", "childWin");

这样, childWin 就代表子窗口了。紧接着这一行,我们用子窗口 childWin 的一个变量, 比如 parentWin 来记住主窗口

childWin.parentWin = this;

这里的 this 是一个很有意思的特殊变量 ,它代表当前的窗口或框架。现在 主窗口和子窗口都已经知道了对方。下面我们就告诉你如何来控制对方。

用子窗口来控制主窗口
在子窗口里,我们可以用变量 parentWin 来控制主窗口。这里我们简单的介 绍一下如何变换主窗口里面的网页。当然你可以控制主窗口里面的其他物体 就象你在主窗口里控制它们一样 ,区别是要加上 parentWin. 在物体和元素 的前面。

如果你想要更换主窗口里面的网页,用下面的语句就可达到

parentWin.location = "new.htm";

更具体一些, 在子窗口里写一个如下的连接

<A href="#" onClick="javascript:parentWin.location='new.htm'">新页</A>

用主窗口来控制子窗口
同样道理 ,你也可以用主窗口里面的子窗口变量来控制子窗口。 比如你想 要更换子窗口里面的网页,用下面的语句就可达到

childWin.location = "new.htm";

更具体一些, 在主窗口里写一个如下的连接

<A href="#" onClick="javascript:childWin.location='new.htm'">新页</A>

 更换多个框架里的网页

这里我们将要回答下面的问题

如何变换多个框架里的网页

假如我们有如下的网页
<html>
<frameset cols="30%,70%">
<frame src="page1.htm" name="frame1">
<frame src="page2.htm" name="frame2">
</frameset>
</html>

我们打算在第一个框架里面加一个连接。当点击这个连接的时候。我们不但能够变换 第二个框架里的网页,我们也想变换第一个框架本身的网页。

page1.htm

<html>
<body>
<h1>This is page 1 </h1>
<a href="page3.htm" onClick="parent.frame2.location='page4.htm'">Click Here</a>
</body>
</html>

同样道理我们可以同时改变多个框架的网页。比如我们写一个Javascript的子程序

function loadFrames()
{
parent.frame1.location='page1.htm
parent.frame2.location='page2.htm
parent.frame3.location='page3.htm
parent.frame4.location='page4.htm
parent.frame5.location='page5.htm
}

然后在连接里面用onclick来启动这个自程序就可以达到同时更换多个框架内容的效果

<a href="page1_1.htm" onclick="loadFrames()">Click here</a>