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

简介:
 在 使用...(5)中用Show()把菜单显示出来了,Show中的大部分大代码都很好理解,这节主要说一下event的处理,在Show的末尾我们使用了一个AttachEvents()方法来attach鼠标和键盘的事件,该方法的代码如下:
None.gifMenu.prototype.AttachEvents =  function(menuHtml)
None.gif{
None.gif     var menuObj = __MenuCache__[menuHtml.uniqueId];
None.gif     if ( menuObj.m_IsEventAttached )
None.gif    {
None.gif         return;
None.gif    }
None.gif     var doc = menuObj.m_Popup.document;
None.gif     for (  var i=0 ; i < menuObj.m_Items.length ; ++i )
None.gif    {
None.gif         var mItem = menuObj.m_Items[i];
None.gif         var trItem = doc.getElementById(mItem.m_Id);
None.gif         if ( mItem.m_Action && !mItem.m_ChildMenu )
None.gif        {
None.gif             if ( !mItem.IsSeparator() )
None.gif            {
None.gif                trItem.attachEvent('onclick', mItem.m_Action);
None.gif                trItem.attachEvent('onclick', Menu.HideAllPopups);
None.gif            }
None.gif        }
None.gif         if ( mItem.m_ChildMenu )
None.gif        {
None.gif            trItem.attachEvent('onmousedown',  this.InnerShow);
None.gif        }
None.gif         if ( !mItem.IsSeparator() )
None.gif        {
None.gif            trItem.attachEvent('onmouseover',  this.ActiveItem);
None.gif        }
None.gif    }
None.gif    menuHtml.attachEvent('onmouseout',  this.ResumeItem);
None.gif     if ( doc )
None.gif    {
None.gif        doc.attachEvent('onkeydown',  this.Keydown);
None.gif    }
None.gif    menuObj.m_IsEventAttached =  true;
None.gif};
    方法中的第一句: var menuObj = __MenuCache__[menuHtml.uniqueId];,就是我在 使用...(3)中说过的为什么要用__MenuCache__。因为menuObj是JavaScirpt类实例,而menuHtml是DHTML的UI元素,他们在使用innerHTML赋值传递时失去了彼此的引用联系,而__MenuCache__里mapping了它们的一对一关系。Menu类中还有很多方法中都用到了类似__MenuCache__[id]这样的调用,而所有用到这种方法的地方,都是为了把object和html映射起来。

    由于attachEvent方法的操作类似一个压栈的过程,执行它是不会检查同一个事件是否已被attach了的,所以需要自己记录菜单是否已attach事件的标志,在执行attach操作前判断。第二个要注意的是,在向事件上attach处理方法时,由于方法都是Menu类内部的方法,都是使用 this.MethodName来引用的,而在这些方法的实现中,是不能使用 this这个关键字来指代Menu类的当前实例的,我下面用 this.ResumeItem的调用来说明,ResumeItem()的源代码如下:
None.gifMenu.prototype.ResumeItem =  function(evt)
None.gif{
None.gif     if ( !evt || evt.toElement )
None.gif    {
None.gif         return;
None.gif    }
None.gif     var menuHtml = FindParentElement(evt.srcElement, 'TABLE');
None.gif     if ( !menuHtml.uniqueId ) 
None.gif    {
None.gif        menuHtml = FindParentElement(menuHtml.parentElement, 'TABLE');
None.gif    }
None.gif     var menuObj =  __MenuCache__[menuHtml.uniqueId];
None.gif     if ( menuObj.HasSubMenuExpanded() )
None.gif    {
None.gif         return;
None.gif    }
None.gif     if ( menuObj.m_ShowTimer )
None.gif    {
None.gif        window.clearTimeout(menuObj.m_ShowTimer);
None.gif        menuObj.m_ShowTimer =  null;
None.gif    }
None.gif    menuObj.__resumeItem();
None.gif};
    这个menuHtml.attachEvent('onmouseout',  this.ResumeItem);事件是用来处理鼠标离开了最末级子菜单时,取消菜单条目的选种状态的。随便点开一个系统菜单,把鼠标移到任何一个条目上,该条目就会被highlight,不做任何点击操作,把鼠标移出菜单,该菜单中被highlight的item就会被resume,这个方法就是实现这个效果的。它的关键是判断 !evt || evt.toElement 是否不为真。

    继续说this引用的问题,当这个onmouseout事件被触发时,方法默认的第一个参数是其window上的event,这个我在使用...(3)中说过,还用红色标识出来了的。而这时ResumeItem里的this引用的是当前菜单所在的父IE窗口,所以获得菜单实例的方法仍然是从__MenuCache__里去取(代码中加下划线的语句)。同时除了ResumeItem,所有在AttachEvents里的attach的方法,InnerShow、ActiveItem和Keydown等,里面都不会有对this的调用(除非确实要引用父IE窗口)。 


本文转自博客园鸟食轩的博客,原文链接:http://www.cnblogs.com/birdshome/,如需转载请自行联系原博主。 

目录
相关文章
|
存储 IDE 前端开发
SpringBoot2.x系列教程02--新纪元之SpringBoot创建Web项目的常用方式
前言 在上一章节中,壹哥 给大家介绍了SpringBoot的优缺点,并重点介绍了其”约定大于配置“的思想,你现在还能记得吗? 而且上文中,壹哥 说我们创建SpringBoot项目有3种方式,我们已经学习了第一种创建项目的方式了,接下来还有另外两种创建项目的方式,这两种方式该怎么创建项目呢?今天 壹哥 就把剩余的两种方式也一股脑都抖搂给大家吧。 一. 以官网模板方式创建Web项目(了解) 首先 壹哥 给大家介绍第2种创建Web项目的方式,对于这种方式大家仅做了解即可,其原理与第一种以Spring Initializr创建项目的方式一样。 1. 在spring.io官网下载模板构建项目 首先我们
318 0
|
存储 前端开发 JavaScript
【一步步一起学DApp开发】(四)web3.js 基本使用 | 连接geth | 创建web客户端
【一步步一起学DApp开发】(四)web3.js 基本使用 | 连接geth | 创建web客户端
601 0
|
JSON JavaScript 中间件
【node.js从入门到精通】使用express创建web服务器,路由,进行中间件的创建链接路由及其他中间件
【node.js从入门到精通】使用express创建web服务器,路由,进行中间件的创建链接路由及其他中间件
197 1
【node.js从入门到精通】使用express创建web服务器,路由,进行中间件的创建链接路由及其他中间件
|
NoSQL MongoDB 数据库
MongoDB v4.4.6安装、创建服务及Web客户端访问MongoDB详解
MongoDB v4.4.6安装、创建服务及Web客户端访问MongoDB详解
277 0
MongoDB v4.4.6安装、创建服务及Web客户端访问MongoDB详解
|
数据采集 Go
Go Web编程实战(9)----创建客户端
Go Web编程实战(9)----创建客户端
140 1
|
Java Go
Go Web编程实战(8)----创建HTTP与HTTPS服务器端
Go Web编程实战(8)----创建HTTP与HTTPS服务器端
186 0
Go Web编程实战(8)----创建HTTP与HTTPS服务器端
|
JavaScript
【Node.JS 】创建基本的web服务器
【Node.JS 】创建基本的web服务器
158 0
【Node.JS 】创建基本的web服务器
|
Java Maven
IDEA2022版本创建maven web项目(两种方式)
创建maven web项目有两种方式,一种是使用骨架方式,一种是不使用骨架的方式
685 1
IDEA2022版本创建maven web项目(两种方式)
|
Web App开发 XML 开发框架
WebAPI学习(一)——创建Web API程序
WebAPI学习(一)——创建Web API程序
247 0
|
JavaScript 前端开发
Node.js 创建并封装静态 WEB 服务器
Node.js 创建并封装静态 WEB 服务器
122 0
Node.js 创建并封装静态 WEB 服务器