使用window.createPopup创建无限级跨帧下拉菜单

我的BLOG搬家到 自己的站点
站点链接
RSS
  先帖样子
     使用window.createPopup创建无限级跨帧下拉菜单_第1张图片
使用层或者其他技术所实现的JS菜单不能解决的问题就是这些菜单不能跨帧,也就是说在Frame之间的时候无可奈何,所幸的是IE5+提供了createPopup这个函数,可以提供窗口的创建,使用createPopup需要注意以下几个问题:
1、函数没有任何参数
2、CreatePopup函数返回的值是新窗口的句柄,这个窗口和普通的窗口一样,所有该有的东西都有。
3、新窗口的parent属性可以对父级窗口(调用createPopup函数的窗口进行访问)
4、一个窗口只能创建一个popup窗口,新调用createPopup将会吧以前的窗口关闭。
5、新窗口的内容初始的时候是空的,没有任何内容,使用document.write和document.body.innerHTML设置值
6、窗口显示的时候调用popwindow.show函数,调用契约为 show(left,top, width, height, document.body);最后一个参数指明位置属性相对的对象
7、窗口隐藏直接调用hide函数。
8、在父级窗口中点击鼠标将会自动将popwindow隐藏。
9、销毁父亲窗口不一定销毁其创建的popwindow,前提是保存窗口句柄的对象是否被销毁。
10、使用alt-tab转换窗口的时候,有时这些新窗口会悬浮在桌面顶层,不会随IE窗口转到后台而隐藏(IE6、IE7都是)
11、新窗口的对象不能使用父窗口的CSS风格,需要手工复写
12、新窗口中的链接(Anchors)需要注意点击之后链接显示的窗口是当前的窗口,一般无效。
13、新窗口中的JavaScript出现错误的时候并不会在当前的IE状态栏中提示!
14、新窗口的CSS风格不支持expression,晕!
15、显示窗口的时候(调用show函数)必须指定窗口的位置和大小,尤其是大小,新窗口可不能自动进行缩放!

实现跨帧菜单首先确定显示方式,每一级的菜单都是显示在一个Popwindow中,如前所述,在一个窗口中只能有一个popwindow,如图显示二级菜单就无法显示了,如何解决这个问题呢?
刚才我们提到,popwindow对象本身就是一个完整的窗口对象,要解决这个问题的最直接的办法就是,下级菜单的生成有父亲菜单所在的窗口(不管是主窗口还是popwindow)调用createPopup生成,这样,各级菜单都可以拥有自己的popwindow,而且可以自动的在同级菜单中进行切换,具体的脚本如下

var ele=control== null?event.srcElement:$(control);
/*...*/
var popw=ele.document.parentWindow.window.createPopup();
/*...*/

层次结构可以构造菜单的基本样式,刚才提到,popwindow不支持CSS风格,也就是说需要手工将CSS风格写到popwindow中,写CSS风格可以使用document.write方式或者直接构造styleSheet对象然后插入rule的方式(注意,直接使用document.body.innerHTML写的style标签好像没有生效),我采用前者,主要原因是,我在主窗口中配置菜单的显示风格,而后将这些显示css风格的文本信息直接保存下来,然后对每个新窗口进行写操作,这样就可以保持每级菜单的CSS风格完全一致。
读取主窗口CSS的代码如下

FrameMenuConfig.CssText= "";
    for( var n=0;FrameMenuConfig.CssPrefix!= null && FrameMenuConfig.CssPrefix.length>0 && n<document.styleSheets.length;n++)
    {
       var sts=document.styleSheets[n];
      for( var x=0;x<sts.rules.length;x++)
      {
         var rr=sts.rules[x];
         if(rr.selectorText.indexOf(FrameMenuConfig.CssPrefix)>=0)
        {
          FrameMenuConfig.CssText+=rr.selectorText+ "{"+rr.style.cssText+ "}";
        }
      }
    }

这里使用的是匹配FrameMenuConfig.CssPrefix的CSS风格才写入到新的窗口中。

然后涉及到菜单的数据结构的定义,这个定义比较简单,就不扯了,用膝盖也能想出来。我这边处理的时候为了防止函数被重复定义,使用了简单的类静态函数的方式进行定义。

到现在为止,我们可以画出一层一层的菜单,在每层的菜单项上挂接onmouseover处理函数就可以自动弹出下级菜单,一切看起来已经完成了。

呵呵,好像还有点东西,菜单的链接有问题,如何解决在新窗口中的Anchor链接指向的页面在我们指定的框架中显示?首先还是要强调,每个popupwindow都是一个window对象,使用parent可以取得上级的对象,我的处理方法是在主窗口中定义了一个goto(url,target)的函数,这个函数负责在主窗口中将URL正确的进行跳转,带出来的问题是,怎么让popwindw正确的调用这个函数,第一层菜单使用parent.goto,第二层菜单使用parent.parent.goto,第三层使用.....

最后一个就是解决alt-tab的问题,这个问题说起来也简单,当alt-tab处理的时候隐藏IE窗口会触发document.onfocusout事件,在这个事件中对所有的popwindow 进行关闭即可,实际测试的时候,却发现如果不对IE窗口的内容进行点击操作(鼠标划过不算),不会使得document取得焦点,也就无法触发onfocusout事件,简单的做法是生成菜单之后调用一下document.focus()函数,这个函数可能会将焦点移动,所以不是很好,但是找不到解决的办法了 

没啥藏着掖着的,源代码下载test.rar (7.97 kb)

以下是测试代码,包含鼠标悬停、自动创建和右键菜单,详细请参考压缩包中的东西


< style type= "text/css">
  #fm_MainContainer
  {
    width:100%;
    height:20px;
    border:solid menu 1px;
    background-color:ghostwhite;
    padding:3px;
    font-size:10pt;
    color:menu;
  }
  #fm_MainContainer a
  {
    padding-left:15px;
    padding-right:15px;
    border-left:solid 2px #104E8B;
    border-right:solid 1px #104E8B;
    text-decoration=none;
    color:blue;
    font-size:10pt;
    font-weight:bold;
    background-color:;
  }
  #fm_MainContainer a:hover
  {
    text-decoration=underline;
    color:red;
    background-color:yellow;
  }
  #fm_Container
  {
    background-color:#E8E8E8;
    height:19px;    
    cursor:hand;
    width:150;
    padding-right:3px;
    border-bottom:solid 1px menu;
    border-left:solid 5px #B0C4DE;    
  }
  #fm_Container a
  {
    padding-left:15px;
    padding-right:15px;
    font-size:10pt;
    text-decoration=none;
    color:blue;
    font-weight:normal;    
  }
  #fm_Container a:hover
  {
    text-decoration=underline;
    color:red;
    background: url(goto.png) no-repeat;
  }
< /style>
< script type= "text/javascript"  src= "../framemenu.js">< /script>
< script type= "text/javascript">
   //系统生成的菜单如果包含有下级菜单在菜单项的左边显示的图片
  FrameMenuConfig.FolderImage= "leftbtn.png";
   //系统菜单生成的结构为<div ><a>...</a></div>,此处设置div的显示风格,a的显示风格请附带在div中设置
  FrameMenuConfig.CssPrefix= "#fm_Container";
   //insert函数直接插入一格记录,格式为 父亲代码、节点代码、节点显示文本、节点URL、节点的目标框架,目标框架支持_self和_blank.
  FrameMenu.insert( null, "a", "滚动规划");
   //add2函数插入一个菜单,返回这个菜单的父亲节点的实例,格式为 节点显示文本、节点URL、节点的目标框架,目标框架支持_self和_blank.节点的ID自动生成
  FrameMenu.insert( null, "b", "立项管理").add2( "立项1").add2( "立项2");
   //add函数插入一个菜单,返回这个新的菜单的实例,格式为 节点显示文本、节点URL、节点的目标框架,目标框架支持_self和_blank.节点的ID自动生成
  FrameMenu.insert( null, "c", "工程实施").add( "工程实施1").add( "工程实施1_1");
  FrameMenu.insert( null, "d", "验收管理").add2( "测试用例").add2( "测试用例");
  FrameMenu.insert( null, null, "系统菜单").add2( "用户管理").add2( "测试用例").add2( "测试用例").add( "角色权限").add2( "角色授权").add2( "用户授权").add2( "资源授权");
  FrameMenu.insert( null, null, "帮助系统").add2( "关于本系统").add2( "退出系统");
  FrameMenu.insert( "a", "a1", "本地文件", "localfile.htm", "body");
  FrameMenu.insert( "a", "a12", "新浪网(弹出窗口)", "http://wwww.sina.com", "_blank");
  FrameMenu.insert( "a", "a13", "多级菜单");
  FrameMenu.insert( "a13", "a13_1", "新浪网(本窗口)", "http://www.sina.com", "_self");
  FrameMenu.insert( "a13", "a13_2", "新浪网(本窗口)", "http://www.sina.com");
  FrameMenu.insert( "a13", "a13_3", "新浪网(Body)", "http://www.sina.com", "body");
< /script>
< body topmargin= "0"  leftmargin= "0"  oncontextmenu= "FrameMenuConfig.showMenu();return false;">
  这个是TopFrame,Name=TopFrame
  < div id= "fm_MainContainer">系统菜单是安排在这里滴,嘻嘻< /div>
  < br/>< button onmouseover= "FrameMenuConfig.showMenu()">鼠标悬停方式显示完整菜单< /button>
< script defer>
  FrameMenuConfig.createFrameMenu( "fm_MainContainer", false);
< /script>
< /body>

 

你可能感兴趣的:(window)