鸟食轩

 Microsoft .NET[C#] MVP 2003
随笔 - 429, 文章 - 235, 评论 - 5527, 引用 - 356
数据加载中……

使用Popup窗口创建无限级Web页菜单(1)

    在Web上使用菜单可以极大地节约页面的空间,同时也比较的符合用户从Windows上继承下来的UI操作体验。在以往的Web页菜单设计中,我们普遍使用div嵌套table的方式来实现菜单,这样的菜单有个最致命的问题就是会被<select>覆盖。我们为了解决这个问题,有时我们干脆在显示图层菜单的同时隐藏页面上的所有下拉列表框,在菜单消失的时候,再显示他们。这个方法虽然可以解决问题,而其优化过后还可以只隐藏和下拉列表框相交的列表框,但是这些解决方法都不是十分的完美。还有些小问题,这样的菜单定位很困难,因为在<div>显示的时候,用户可以使用鼠标滚轮滚动页面,这样一来是否要让<div>菜单和页面滚动同步呢?如果不要,页面被滚走了,菜单仍显示在一个和自己毫不相关的位置上很是古怪。如果要同步,那么噩梦就来了,因为被滚动的区域不一定就是<body>区域,还可能是一些类似<div style="overflow:auto"><div>的区域,要算出菜单的位置将会非常的麻烦。

    下面将介绍的Popup来实现的Web页菜单将完全解决<div>做为菜单容器时遇到的问题,Popup窗口是IE5.5及以后版本提供的一个新feature。什么是popup呢?简单说popup其实就是一个弹出窗口,它拥有以下特点(MSDN描述): 
    ·popup窗口在用户点击它自身之外的任何地方或另一个popup打开的时候会自动关闭; 
    ·popup在显示的时候不能获得焦点,所以用户已focused的操作将继续在其父窗口中执行; 
    ·组成popup的DHTML可以存储在其父document或其他的document元素中; 
    ·popup窗口中不支持文本框一类的编辑框element; 
    ·不能选中popup窗口中的元素; 
    ·不能在popup窗口中navigate(点击popup中的连接,不能让更新的内容显示到这个popup中);
    ·popup窗口一旦显示就不能移动和resize。

    这里MSDN说的不全,而且有的地方不是很准确,popup窗口还有几个重要的特性。它可以超出浏览器的窗口范围而且也不会被下拉框、flash、IFrame等这些元素遮挡。实际上popup里的内容是可以被选择的,不知道MSDN说的不能选择是啥意思?。关于MSDN说popup不能获得焦点也有点问题,其实是popup里的编辑框类控件不能获得焦点,而其它的非可编辑控件是可以获得焦点的。而且popup显示的时候,IE主窗口不能获得鼠标的onmousewheel事件。
    这样的一些特性,恰好表明了popup窗口非常的适合用来制作弹出菜单,并且由于popup窗口显示的时候,IE窗口内的文档是不能被移动的,这样就不存在context menu的位置同步问题了,因为毕竟popup窗口不能move(move位置需要hide以后在新的位置上重show),这个问题还比较讨厌。

    使用popup窗口制作无限级别的菜单,有两个问题要解决:一个是要能在一个IE中显示多个Popup窗口,二是要能把窗口中的一些事件俘获并执行我们脚本过程。MSDN在描述popup窗口特性时,第一条就说了只要有另一个popup窗口开启,先前显示的popup窗口就会自动关闭。这下怎么办呢?不过既然都说了要实现无限级的菜单了,办法还是有的。对于popup,使用方式其实是很简单的,他一共就只包含了两个方法:hide()和show(...),和两个属性:document和isOpen。虽然在IE中我们连续的调用n次window.createPopup().show(...)只能出来一个popup窗口被显示,可是我们可以调用popup.document.parentWindow的createPopup方法,它产生的popup窗口在显示的时候就不会关闭前面已显示的popup窗口,并且对于新的popup用这个方法可以继续开启child popup。这个问题再研究下去,会发现IE实现popup的一些怪异的地方(当然这些对于我们实现这个菜单关系不太大,只是觉得混乱)。

    比如我们在一个IE窗口中,var popup = window.createPopup(); var win = popup.document.parentWindow; 我们会发现 window != win,对于多个popup可以共存,这个不相等还能理解,但是当我们调用win.resizeTo(...)的时候,我们发现父IE窗口被resize了。同样我们在popup中select all,结果也是父IE窗口里的内容被全选了@_@...  

    to be continued...

posted on 2004-12-11 08:13 birdshome 阅读(6794) 评论(9)  编辑 收藏 网摘 所属分类: Jscript&Dhtml开发

评论

#1楼   回复  引用  查看    

继续关注中……
2004-12-11 08:42 | RbmxXx      

#2楼   回复  引用    

我一会到你那里去看看
2004-12-27 14:13 | Tiger

#3楼   回复  引用  查看    

不知道鸟食轩是否考虑过scriptlet中的菜单。
2005-02-18 21:16 | 辣妹子      

#4楼[楼主]   回复  引用  查看    

暂时还没有考虑过,因为<object>虽然可以不被页面的其它window级的元素覆盖,不过对于复杂的内容,object用起来也不是很方便。
2005-02-18 23:47 | birdshome      

#5楼   回复  引用  查看    

不知道 birdshome 说的复杂内容指的是什么,如果仅仅是指数据复杂的菜单(其实就界面复杂度来说,我觉得scriptlets也说得过去,毕竟是wndows自身的菜单,对于最终用户来说具有上手的好处),那我想没有那种菜单还能比它更方便。

我觉得使用scriptlets最大的不方便之处在于child和container之间的通讯,不熟悉的话折腾死人。

不好意思,由于不知道 birdshome 是否完全明白我的意思,所以拿了个msdn的例子过来。望勿笑:

11.htm:

<HTML>
<HEAD>
</HEAD>
<body>
<OBJECT width=200 height=123 TYPE="text/x-scriptlet" DATA="Calendar.htm" style="border:1 solid red">
</OBJECT>
</body>
</html>

Calendar.htm

<HTML ID="MyPage">
<HEAD>
</HEAD>
<body>
asdf
</body>
</html>
<script language="VBscript">
dim menuItems(10)
dim bFirstTime

menuItems(0) = "&One"
menuItems(1) = "One"
menuItems(2) = "&Two"
menuItems(3) = "Two"
menuItems(4) = "&Three"
menuItems(5) = "Three"
menuItems(6) = "xxx" ' stub the next items
menuItems(7) = ""' stub the next items

menuItems(6) = "" ' separator
menuItems(7) = "" ' separator
menuItems(8) = "&Four"
menuItems(9) = "Four"
window.external.setContextMenu(menuItems)

Sub One
MsgBox "One"
End Sub

Sub Two
MsgBox "Two"
End Sub

Sub Three
MsgBox "Three"
End Sub

Sub Four
MsgBox "Four"
End Sub
</script>

birdshome ,你能在象上面一样这么简单的代码中创建这么好的菜单吗?我拭目以待。

^_^
2005-02-19 06:07 | 辣妹子      

#6楼   回复  引用    

哇,看来必须好好研究一下了~~
2005-02-19 18:45 | birdshome

#7楼   回复  引用    

我发现了1个方法

#8楼   回复  引用    

<OBJECT id=menu type="application/x-oleobject" classid="clsid:adb880a6-d8ff-11cf-9377-00aa003b7a11">
<PARAM name="Command" value="Related Topics,menu">
<PARAM name="Item1" value="#">
<PARAM name="Item2" value="#">
<PARAM name="Item3" value="#">
<PARAM name="Item4" value="#">
<PARAM name="Item5" value="#">
</OBJECT>
<script>
if (document.all)
document.body.onmousedown=new Function("if (event.button==2) menu.Click();")
</script>




你看看这个!!0-0!!哈哈哈

#9楼[楼主]   回复  引用  查看    

@我发现了1个方法 NikaJa
scriptlet微软已经不推荐使用了
2007-08-03 17:12 | birdshome      



发表评论

昵称: [登录] [注册]

主页:

邮箱:(仅博主可见)

评论内容:

  登录  注册

[使用Ctrl+Enter键快速提交评论]

0 75487




相关文章:

相关链接: