动态HTML创作之嵌入层

      爱好无限 2004-7-11 14:19
  现在了解一下“嵌入层”的概念,它与“剪切层”有一定的关系,但不完全相同。这所以到现在才介绍“嵌入层”是因为它们将影响一些代码中的Script程序。

当想要把一些层组合成为一个统一的元素时就需要用到“嵌入层”。换句话说,嵌入层就是将层放入层中。

当进行这些处理时,“子层”的放置位置是根据它们的“父层”来决定的。并且,当父层被剪切时,子层的显示就像是在窗口或外挂程序中一样。如果子层超出了父层的边框,那么那些部分是不可见的,但子层的可见性属性并未改变,但是超出的部分就像出了屏幕的边界,被隐藏起来。

如果在学习复杂的定位技术时,就会觉得“嵌入”技术其实很容易上手的。因为既然所有子层的位置都由父层决定,那么子层就被永久地“锁定”。如果以后想要移动父层的位置,也不必改变子层的位置,因为它们会相应地移动。这对于滑动动画同样适用,所有子层将一起移动。

非常不幸,嵌入层的javascript在Netscape和Internet Explorer中几乎完全不同,要使它在两个浏览器中同样好地工作真是让人有点头疼,这也是为什么在网络上很少看到嵌入层的原因。但是,不管怎样,我们已经找到了一些技术来对付这些问题。所以看来得先忍受一下,因为一旦学会使用嵌入层,就会发现它是非常有用的,甚至希望把它用于所有的网页。

样式表单与嵌入

要嵌入层,所需做的就是把子层的<DIV>包括到父层的<DIV>里去:

<DIV ID=“parent1Div”>

<DIV ID=“child1Div”>

......

<DIV ID=“child2Div”>

......

</DIV>

</DIV>

可能已经注意到了我们没有把样式(style)加入这些<DIV>标记中。那是因为如果用“行内”定义的方式定义样式,Netscape就不会让你来嵌入层!所以从现在开始就一直使用<STYLE>标记定义样式,所有的例子都将用这种方式(如果想了解CSS定义样式的三种方法,请参阅CSS>

这些CSS都基本相同只不过它们都被从<DIV>标记中分离出来:
<HTML>

<HEAD>
<TITLE>DHTML Demo</TITLE>
<style type="text/css">
<!--
#parent1Div{position:absolute;
left:100;
top:80;
width:230;
height:120;
clip:rect(0,230,120,0);
background-color:#c0c0c0;
layer-background-color:#c0c0c0;
}
#child1Div{position:absolute;
left:-20;
top:40;
width:70;
height:70;
clip:rect(0,70,70,0);
background-color:#ff0000;
layer-background-color:#ff0000;
}
#child2Div{position:absolute;
left:180;
top:70;
width:70;
height:70;
clip:rect(0,70,70,0);
background-color:#0000ff;
layer-background-color:#0000ff;
}
//-->
</style>
</HEAD>

<BODY>
<div id="parent1Div">
<div id="child1Div"></div>
<div id="child2Div"></div>
</div>
</BODY>
</HTML>
上面的例子的演示效果可以看到层的关系。

javascript和嵌入

对于Netscape和Internet Explorer来说,嵌入层的方法完全相反的,在Internet Explorer里,一个层是否嵌入并没有什么区别,可以使用同样的方法来访问这个层的属性。像这样:

childLayer.style.properyName

但是,在Netscape里,当要访问一个嵌入层(子层)的属性时,必须要指定它的父层是谁:

document.parentLayer.document.childLayer.propertyName

在层名字前附加的“document”是因为Netscape把层当作一个分离的文档,子层是父层的一部分。要嵌入多少层的数目是没有限定的,只要不停地嵌套<DIV>标记就可以了。

这个概念可以加入到前面提到的“pointer”变量中,这里有一个例子:.
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
}
}
重温CSS属性

Internet Explorer有些技术让我们陷入窘境并且困惑了好一阵子。当用<STYLE>标记定义层的样式时,Internet Explorer的初始设置不会让你读取任何的属性。所以当在IE中要检查当前“父层”的位置,如果写:

alert(parent1.left)

将会发现不会得到任何的值。所有的CSS属性都不会显示。下面有一个例子来检查层的属性。在Netscape里,一切运行良好而在Internet Explorer中警告框将呈现空白状。让我们来试验一下这个有趣的现象:

<HTML>

<HEAD>
<TITLE>DHTML Demo</TITLE>
<script language="javascript">
<!--

ns4=(document.layers)?true:false
ie4=(document.all)?true:false

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
}
}
//-->
</script>
<style type="text/css">
<!--
#parent1Div {position:absolute;left:180;top:100;width:230;
height:120;clip:rect(0,230,120,0);
background-color:#c0c0c0;
layer-background-color:#c0c0c0}
#child1Div {position:absolute;left:-20;top:40;width:70;
height:70;clip:rect(0,70,70,0);
background-color:#ff0000;
layer-background-color:#ff0000}
#child2Div {position:absolute;left:180;top:70;width:70;
height:70;clip:rect(0,70,70,0);
background-color:#0000ff;
layer-background-color:#0000ff}
//-->
</style>
</HEAD>

<BODY onLoad="init()">
<div id="parent1Div">
<div id="child1Div"></div>
<div id="child2Div"></div>
</div>
<p>检测值:
<br>父层 1:<a href="javascript:alert(parent1.left)">left</a>,
<a href="javascript:alert(parent1.top)">top</a>,
<a href="javascript:alert(parent1.visibility)">visibility</a>
<br>子层 1:<a href="javascript:alert(child1.left)">left</a>,
<a href="javascript:alert(child1.top)">top</a>,
<a href="javascript:alert(child1.visibility)">visibility</a>
<br>子层 2:<a href="javascript:alert(child2.left)">left</a>,
<a href="javascript:alert(child2.top)">top</a>,
<a href="javascript:alert(child2.visibility)">visibility</a>
</p>
</BODY>
</HTML>
假设我们分别点击“子层1”的三个属性值,那么Netscape会如实地告诉我们,但是Internet Explorer的警告框呈现空白状!<点击此处查看>对此,我们仍然不明白为什么微软会把IE做成这样,因为这看起来有些过于笨拙。这种情况仅仅在使用<STYLE>标记时发生,而且仅仅影响属性的初始值。

上面的结果会产生什么影响呢?答案是,如果想要像先前那样分配其他属性,那么就需要知道它现在的位置,因此在IE4.0里既然无法获取当前的属性,就必须用其他方法。好在微软在IE4.0里包含了一些附加的非标准的CSS属性。

l pixelLeft

l pixelTop

l pixelWidth

l pixelHeight

这些附加的属性不受IE的<STYLE>标记的影响,所以我们可以使用这些属性来获得层的位置。
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
}
}
请将上面代码粘贴到前面一个例子的Scripting部分,并对后面的“alert()”部分修改“xpos”、“ypos”,然后使用IE来检测一下效果,虽然IE仍然不能显示“visibility”属性,但是它已经能够告诉我们各个层当前的像素位置,这是一个不小的进步。接下来就可以尝试着让用户来改变层的位置,请看一个完整的例子:

<HTML>

<HEAD>
<TITLE>DHTML Demo</TITLE>
<script language="javascript">
<!--

ns4=(document.layers)?true:false
ie4=(document.all)?true:false

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
}
}

function move(obj,x,y) {
obj.xpos+=x
obj.ypos+=y
obj.left=obj.xpos
obj.top=obj.ypos
}

//-->
</script>
<style type="text/css">
<!--
#parent1Div {position:absolute;left:200;top:80;width:230;
height:120;clip:rect(0,230,120,0);
background-color:#c0c0c0;
layer-background-color:#c0c0c0}
#child1Div {position:absolute;left:-20;top:40;width:70;
height:70;clip:rect(0,70,70,0);
background-color:#ff0000;
layer-background-color:#ff0000}
#child2Div {position:absolute;left:180;top:70;width:70;
height:70;clip:rect(0,70,70,0);
background-color:#0000ff;
layer-background-color:#0000ff}
//-->
</style>
</HEAD>

<BODY onLoad="init()">
<div id="parent1Div">
<div id="child1Div"></div>
<div id="child2Div"></div>
</div>
<p>检测值:
<br>父层 1:<a href="javascript:alert(parent1.xpos)">left</a>,
<a href="javascript:alert(parent1.ypos)">top</a>
<br>子层 1:<a href="javascript:alert(child1.xpos)">left</a>,
<a href="javascript:alert(child1.ypos)">top</a>
<br>子层 2:<a href="javascript:alert(child2.xpos)">left</a>,
<a href="javascript:alert(child2.ypos)">top</a>
</p>
<p>改变值:
<br>父层 1:<a href="javascript:move(parent1,0,-10)">上</a>,
<a href="javascript:move(parent1,0,10)">下</a>,
<a href="javascript:move(parent1,-10,0)">左</a>,
<a href="javascript:move(parent1,10,0)">右</a>
<br>子层 1:<a href="javascript:move(child1,0,-10)">上</a>,
<a href="javascript:move(child1,0,10)">下</a>,
<a href="javascript:move(child1,-10,0)">左</a>,
<a href="javascript:move(child1,10,0)">右</a>
<br>子层 2:<a href="javascript:move(child2,0,-10)">上</a>,
<a href="javascript:move(child2,0,10)">下</a>,
<a href="javascript:move(child2,-10,0)">左</a>,
<a href="javascript:move(child2,10,0)">右</a>
</p>
</body>
</HTML>
当在“改变值”里不停地按动任意一个链接后,这些层就会按照用户的意愿上下左右地移动,有点游戏的味道吧,是不是觉得有趣?

可见性和嵌入

前面已经看到,在IE4.0中,如果用<STYLE>标记来定义层的可见性,就不会获得这个可见性的属性值,但是就一般的使用经验来看,很少需要去获取层的可见性。通常,一个层是否可见是一目了然的,当用javascript改变可见性值后,又可以正常使用了,所以不必去费心让IE返回可见性的初始值。

但是有一点必须指出:如果不定义子层的可见性属性,那么它的可见性是“继承的”,即依据父层的可见性来定, 在那种情况下当显示或隐藏父层时,所有的子层也将跟着做。但是注意,在Netscape里如果既定义子层的可见性,又在javascript里改变属性,那将马上失去隐藏或显示所有的子层的能力,在那样的情况下,当隐藏父层时,所有的子层将仍然显现着。

请看有关这个方面描述的例子,当然,最好用Netscape来检验这个现象:

<HTML>

<HEAD>
<TITLE>DHTML Demo</TITLE>
<script language="javascript">
<!--

ns4=(document.layers)?true:false
ie4=(document.all)?true:false

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
}
}

function showObject(obj) {
if(ns4) obj.visibility="show"
else if(ie4) obj.visibility="visible"
}

function hideObject(obj) {
if(ns4) obj.visibility="hide"
else if(ie4) obj.visibility="hidden"
}
//-->
</script>
<style type="text/css">
<!--
#parent1Div {position:absolute;left:180;top:100;width:230;
height:120;clip:rect(0,230,120,0);
background-color:#c0c0c0;
layer-background-color:#c0c0c0}
#child1Div {position:absolute;left:-20;top:40;width:70;
height:70;clip:rect(0,70,70,0);
background-color:#ff0000;
layer-background-color:#ff0000}
#child2Div {position:absolute;left:180;top:70;width:70;
height:70;clip:rect(0,70,70,0);
background-color:#0000ff;
layer-background-color:#0000ff}
//-->
</style>
</HEAD>

<BODY onLoad="init()">
<div id="parent1Div">
<div id="child1Div"></div>
<div id="child2Div"></div>
</div>
<p>使用方法:首先,隐藏和显示父层。你将会看到所有的子层都会跟着这么做。然后隐藏和显示两个子层,然后再一次地隐藏和显示父层,此时,你就会看到子层总是保持可见。
</p>
<p>改变可见性:
<br>父层 1:<a href="javascript:hideObject(parent1)">隐藏</a>,
<a href="javascript:showObject(parent1)">显示</a>
<br>子层 1:<a href="javascript:hideObject(child1)">隐藏</a>,
<a href="javascript:showObject(child1)">显示</a>
<br>子层 2:<a href="javascript:hideObject(child2)">隐藏</a>,
<a href="javascript:showObject(child2)">显示</a>
</p>
</BODY>
</HTML>
正如程序中所介绍的,在Netscape中的使用方法为,首先,隐藏和显示父层。所有的子层都将会跟着这么做,然后隐藏和显示两个子层,然后再一次地隐藏和显示父层,此时,就会看到子层总是保持可见。

同时,如果使用IE来试验上面的例子,就不会产生错误。

因此,正如所期望的那样,我们所需要的最终结果就和IE一样:无论在何种情况下,当隐藏父层时所有可见和不可见的子层都将被隐藏;当显示父层是,只有先前可见的子层才被显示,而先前不可见的子层将保留“可见性轨迹”仍然被隐藏。

让我们看看有关这个“保留可见性轨迹”的例子:

<HTML>

<HEAD>
<TITLE>DHTML Demo</TITLE>
<script language="javascript">
<!--

ns4=(document.layers)?true:false
ie4=(document.all)?true:false

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
}
parent1.vis=true
child1.vis=true
child2.vis=true
}

function showObject(obj) {
if(ns4) obj.visibility="show"
else if(ie4) obj.visibility="visible"
}

function hideObject(obj) {
if(ns4) obj.visibility="hide"
else if(ie4) obj.visibility="hidden"
}

function showParent1() {
showObject(parent1)
parent1.vis=true
if(child1.vis) showObject(child1)
if(child2.vis) showObject(child2)
}

function hideParent1() {
hideObject(parent1)
parent1.vis=false
if(child1.vis) hideObject(child1)
if(child2.vis) hideObject(child2)
}

function showChild1() {
child1.vis=true
if(parent1.vis) showObject(child1)
}
function hideChild1() {
child1.vis=false
hideObject(child1)
}

function showChild2() {
child2.vis=true
if(parent1.vis) showObject(child2)
}
function hideChild2() {
child2.vis=false
hideObject(child2)
}
//-->
</script>
<style type="text/css">
<!--
#parent1Div {position:absolute;left:180;top:100;width:230;
height:120;clip:rect(0,230,120,0);
background-color:#c0c0c0;
layer-background-color:#c0c0c0}
#child1Div {position:absolute;left:-20;top:40;width:70;
height:70;clip:rect(0,70,70,0);
background-color:#ff0000;
layer-background-color:#ff0000}
#child2Div {position:absolute;left:180;top:70;width:70;
height:70;clip:rect(0,70,70,0);
background-color:#0000ff;
layer-background-color:#0000ff}
//-->
</style>
</HEAD>

<BODY onLoad="init()">
<div id="parent1Div">
<div id="child1Div"></div>
<div id="child2Div"></div>
</div>
<p>改变可见性:
<br>父层 1:<a href="javascript:hideParent1()">隐藏</a>,
<a href="javascript:showParent1()">显示</a>
<br>子层 1:<a href="javascript:hideChild1()">隐藏</a>,
<a href="javascript:showChild1()">显示</a>
<br>子层 2:<a href="javascript:hideChild2()">隐藏</a>,
<a href="javascript:showChild2()">显示</a>
</p>
</BODY>
</HTML>
无论用何种浏览器来检验,同时无论在什么情况下,当隐藏父层时子层都会跟着被隐藏。这也就达到了我们所需的效果


标签集:TAGS:
回复Comments() 点击Count()

回复Comments

{commentauthor}
{commentauthor}
{commenttime}
{commentnum}
{commentcontent}
作者:
{commentrecontent}
}