使用Popup窗口创建无限级Web页菜单(7)-阿里云开发者社区

开发者社区> 唐玄奘> 正文

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

简介:
+关注继续查看
  这一节主要说一下Menu对键盘的支持,本来不支持键盘这个菜单也完全可用了,不过还是为了和WinForm的Menu统一,所以支持了和WinForm菜单一样的操作方式。

    菜单的处理函数Menu.prototype.Keydown是在AttachEvents()方法里通过:
None.gifdoc.attachEvent('onkeydown', this.Keydown);None.gif
来attach的,为什么要使用onkeydown不用onkeypress呢?是为了让菜单通过键盘快捷键来弹出子菜单时和WinForm方式菜单一样。这个doc是该菜单的popup窗口的doucment对象。

    下面一边看代码一边讲吧:
None.gif    if ( !evt || !evt.srcElement )
None.gif    {
None.gif        return;
None.gif    }
None.gif    var menuBody = evt.srcElement;
None.gif    var menuHtml = FindChildElement(menuBody, 'TABLE');
None.gif    if ( !menuHtml || !menuHtml.uniqueId )
None.gif    {
None.gif        menuHtml = FindParentElement(menuBody, 'TABLE');
None.gif        if ( !menuHtml || !menuHtml.uniqueId )
None.gif        {
None.gif            return;
None.gif        }
None.gif    }
None.gif    var menuObj = __MenuCache__[menuHtml.uniqueId];
None.gif    if ( menuObj.HasSubMenuExpanded() )
None.gif    {
None.gif        return;
None.gif    }
    由于onkeydown事件处理函数attach在document上,所以要得到菜单必须寻找body里面的Table element,不过这个evt.srcElement可能是body,也可能是table的里的元素,关键是看当时菜单popup里的焦点在那个element上。上面代码的最后4句话是判断响应onkeydown事件的菜单是否有子菜单expanded,因为我们只让最后一级显示的子菜单处理keystroke,父级的必须忽略,否则就乱套了。
None.gif    if ( menuObj.m_ShowTimer )
None.gif    {
None.gif        window.clearTimeout(menuObj.m_ShowTimer);
None.gif        menuObj.m_ShowTimer = null;
None.gif    }
    这是用来支持子菜单显示特效的一个timer,如果手动显示子菜单(包括鼠标click和键盘快捷键),清除这个timer。

None.gif    var activeIndex = -1;
None.gif    for ( var i=0 ; i < menuObj.m_Items.length ; ++i )
None.gif    {
None.gif        if ( menuObj.m_ActiveItem == menuObj.m_Items[i] )
None.gif        {
None.gif            activeIndex = i;
None.gif            break;
None.gif        }
None.gif    }
    把菜单中已active的item的index搜索出来,没有active的menuitem,index为-1。

None.gif    var sign = -1; 
None.gif    switch( evt.keyCode )
None.gif    {
None.gif        case 37 : // left
None.gif
        {
None.gif            if ( menuObj.m_ParentMenu )
None.gif            {
None.gif                menuObj.Hide();
None.gif            }
None.gif            break;
None.gif        }
None.gif        case 38 : // up | no break;
None.gif
        {
None.gif            sign = 1;
None.gif            if ( activeIndex == -1 )
None.gif            {
None.gif                activeIndex = 0;
None.gif            }
None.gif        }
None.gif        case 40 : // down
None.gif
        {
None.gif            var itemCount = menuObj.m_Items.length;
None.gif            for ( var i=1 ; i <= itemCount ; ++i )
None.gif            {
None.gif                var index = (itemCount+activeIndex-i*sign)%itemCount;
None.gif                var item = menuObj.m_Items[index];
None.gif                if ( !item.m_Disabled && item.m_Text != '-' )
None.gif                {
None.gif                    menuObj.__resumeItem();
None.gif                    menuObj.m_ActiveItem = item;
None.gif                    menuObj.__activeItem();
None.gif                    break;
None.gif                }
None.gif            }
None.gif            break;
None.gif        }
None.gif        case 39 : // right | no break;
None.gif
        {
None.gif            var activeItem = menuObj.m_ActiveItem; 
None.gif            if ( !activeItem || !activeItem.m_ChildMenu )
None.gif            {
None.gif                break;
None.gif            }
None.gif        }
None.gif        case 13 : // enter
None.gif
        {
None.gif            menuObj.Click();
None.gif            break;
None.gif        }
None.gif        case 27 :
None.gif        {
None.gif            break;
None.gif        }
None.gif    }
    处理left, right, up, down四个键,up和down要麻烦些,因为要查找可用的(separator item和disabled item是不可用的,不能被active)下一个itme来active,到了最有一条itme再同方向up或down还需要有轮转的效果。
    HACK: 由于up和down的代码完全相同,只是搜索方向不同,所以用了一个sign(取值1|-1)标志来判断搜索方向。

None.gif    if ( evt.keyCode >= 48 && evt.keyCode <= 90 )
None.gif    {
None.gif        var keyList = '';
None.gif        var key = String.fromCharCode(evt.keyCode); 
None.gif        for ( var i=0 ; i < menuObj.m_Items.length ; ++i )
None.gif        {
None.gif            var item = menuObj.m_Items[i];
None.gif            if ( !item.m_Disabled && item.m_Mnemonic )
None.gif            { 
None.gif                keyList += item.m_Mnemonic;
None.gif            }
None.gif            else
None.gif            {
None.gif                keyList += '-';
None.gif            }
None.gif        }
None.gif        var index = keyList.indexOf(key); 
None.gif        if ( index != -1 )
None.gif        { 
None.gif            if ( keyList.indexOf(key) == keyList.lastIndexOf(key) )
None.gif            {
None.gif                if ( !menuObj.m_Items[index].m_Disabled )
None.gif                {
None.gif                    menuObj.__resumeItem(); 
None.gif                    menuObj.m_ActiveItem = menuObj.m_Items[index];
None.gif                    menuObj.__activeItem();
None.gif                    menuObj.Click();
None.gif                }
None.gif            }
None.gif            else
None.gif            {
None.gif                menuObj.__resumeItem();
None.gif                var newActive;
None.gif                if ( !evt.shiftKey )
None.gif                {
None.gif                    newActive = keyList.indexOf(key, activeIndex+1);
None.gif                }
None.gif                else
None.gif                {
None.gif                    if ( activeIndex == 0 )
None.gif                    {
None.gif                        newActive = -1;
None.gif                        index = keyList.lastIndexOf(key);
None.gif                    }
None.gif                    else 
None.gif                    {
None.gif                        newActive = keyList.lastIndexOf(key, activeIndex-1);
None.gif                    }
None.gif                }
None.gif                     
None.gif                if ( newActive == -1 )
None.gif                {
None.gif                    menuObj.m_ActiveItem = menuObj.m_Items[index];
None.gif                }
None.gif                else
None.gif                {
None.gif                    menuObj.m_ActiveItem = menuObj.m_Items[newActive];
None.gif                }
None.gif                menuObj.__activeItem();
None.gif            }
None.gif        }
None.gif    }
None.gif
    处理菜单条目上的快捷键Mnemonic,这里的算法是这样的,把该菜单上的每个item上的Mnemonic字符取出组成一个字符串,没有Mnemonic就用'-'代替。比如下面的菜单的Mnemonic字符组成的字符串分别是:
   contextmenu2.gif 
    第一级:"--N---",第二级:"M",第三级:"TTTT"。然后使用String.indexOf(key)就取到被按快捷键的MenuItem的index了,由于没有限制同一个Menu里面多个MenuItem具有相同的Mnemonic,所以像第三级菜单,一直按T键的效果就和按down key一样,它的效果使用语句Sting.indexOf(key, activeIndex+1)来获得。 

ExpandedBlockStart.gif#region 附Menu.prototype.Keydown = function(evt)代码 
None.gifMenu.prototype.Keydown = function(evt)
None.gif{
None.gif    if ( !evt || !evt.srcElement )
None.gif    {
None.gif        return;
None.gif    }
None.gif    var menuBody = evt.srcElement;
None.gif    var menuHtml = FindChildElement(menuBody, 'TABLE');
None.gif    if ( !menuHtml || !menuHtml.uniqueId )
None.gif    {
None.gif        menuHtml = FindParentElement(menuBody, 'TABLE');
None.gif        if ( !menuHtml || !menuHtml.uniqueId )
None.gif        {
None.gif            return;
None.gif        }
None.gif    }
None.gif    var menuObj = __MenuCache__[menuHtml.uniqueId];
None.gif    if ( menuObj.HasSubMenuExpanded() )
None.gif    {
None.gif        return;
None.gif    }
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
None.gif    var activeIndex = -1;
None.gif    for ( var i=0 ; i < menuObj.m_Items.length ; ++i )
None.gif    {
None.gif        if ( menuObj.m_ActiveItem == menuObj.m_Items[i] )
None.gif        {
None.gif            activeIndex = i;
None.gif            break;
None.gif        }
None.gif    }
None.gif    var sign = -1; 
None.gif    switch( evt.keyCode )
None.gif    {
None.gif        case 37 : // left
None.gif
        {
None.gif            if ( menuObj.m_ParentMenu )
None.gif            {
None.gif                menuObj.Hide();
None.gif            }
None.gif            break;
None.gif        }
None.gif        case 38 : // up | no break;
None.gif
        {
None.gif            sign = 1;
None.gif            if ( activeIndex == -1 )
None.gif            {
None.gif                activeIndex = 0;
None.gif            }
None.gif        }
None.gif        case 40 : // down
None.gif
        {
None.gif            var itemCount = menuObj.m_Items.length;
None.gif            for ( var i=1 ; i <= itemCount ; ++i )
None.gif            {
None.gif                var index = (itemCount+activeIndex-i*sign)%itemCount;
None.gif                var item = menuObj.m_Items[index];
None.gif                if ( !item.m_Disabled && item.m_Text != '-' )
None.gif                {
None.gif                    menuObj.__resumeItem();
None.gif                    menuObj.m_ActiveItem = item;
None.gif                    menuObj.__activeItem();
None.gif                    break;
None.gif                }
None.gif            }
None.gif            break;
None.gif        }
None.gif        case 39 : // right | no break;
None.gif
        {
None.gif            var activeItem = menuObj.m_ActiveItem; 
None.gif            if ( !activeItem || !activeItem.m_ChildMenu )
None.gif            {
None.gif                break;
None.gif            }
None.gif        }
None.gif        case 13 : // enter
None.gif
        {
None.gif            menuObj.Click();
None.gif            break;
None.gif        }
None.gif        case 27 :
None.gif        {
None.gif            break;
None.gif        }
None.gif    }
None.gif    if ( evt.keyCode >= 48 && evt.keyCode <= 90 )
None.gif    {
None.gif        var keyList = '';
None.gif        var key = String.fromCharCode(evt.keyCode); 
None.gif        for ( var i=0 ; i < menuObj.m_Items.length ; ++i )
None.gif        {
None.gif            var item = menuObj.m_Items[i];
None.gif            if ( !item.m_Disabled && item.m_Mnemonic )
None.gif            { 
None.gif                keyList += item.m_Mnemonic;
None.gif            }
None.gif            else
None.gif            {
None.gif                keyList += '-';
None.gif            }
None.gif        }
None.gif        var index = keyList.indexOf(key); 
None.gif        if ( index != -1 )
None.gif        { 
None.gif            if ( keyList.indexOf(key) == keyList.lastIndexOf(key) )
None.gif            {
None.gif                if ( !menuObj.m_Items[index].m_Disabled )
None.gif                {
None.gif                    menuObj.__resumeItem(); 
None.gif                    menuObj.m_ActiveItem = menuObj.m_Items[index];
None.gif                    menuObj.__activeItem();
None.gif                    menuObj.Click();
None.gif                }
None.gif            }
None.gif            else
None.gif            {
None.gif                menuObj.__resumeItem();
None.gif                var newActive;
None.gif                if ( !evt.shiftKey )
None.gif                {
None.gif                    newActive = keyList.indexOf(key, activeIndex+1);
None.gif                }
None.gif                else
None.gif                {
None.gif                    if ( activeIndex == 0 )
None.gif                    {
None.gif                        newActive = -1;
None.gif                        index = keyList.lastIndexOf(key);
None.gif                    }
None.gif                    else 
None.gif                    {
None.gif                        newActive = keyList.lastIndexOf(key, activeIndex-1);
None.gif                    }
None.gif                }
None.gif                     
None.gif                if ( newActive == -1 )
None.gif                {
None.gif                    menuObj.m_ActiveItem = menuObj.m_Items[index];
None.gif                }
None.gif                else
None.gif                {
None.gif                    menuObj.m_ActiveItem = menuObj.m_Items[newActive];
None.gif                }
None.gif                menuObj.__activeItem();
None.gif            }
None.gif        }
None.gif    }
None.gif    if ( evt.keyCode != 27 )
None.gif    {  
None.gif        evt.returnValue = null;
None.gif        evt.cancelBubble = true
None.gif    }
None.gif};

    to be continued ...

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

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
使用 SAP WebIDE 创建 SAP Fiori Elements 应用
使用 SAP WebIDE 创建 SAP Fiori Elements 应用
8 0
分享录制的正则表达式入门、高阶以及使用 .NET 实现网络爬虫视频教程
我发布的「正则表达式入门以及高阶教程」,欢迎学习。 课程简介 正则表达式是软件开发必须掌握的一门语言,掌握后才能很好地理解到它的威力; 课程采用概念和实验操作 4/6 分隔,帮助大家理解概念后再使用大量的实例加深对概念的理解; 实例操作是对概念最好的理解,也是学习新语言最有效的办法; 在课程中也穿插着大量软件开发的技巧和大家分享; 应该是把晦涩的正则表达式讲解的最生动的课程; 掌握了正则表达式后,您一定会觉得这是一门最值得掌握的语言。
886 0
lua使用io.open跨平台文件夹遍历匹配查找
-- Desc :实现在LUA_PATH中的lua文件中遍历寻找没用到PNG_PATH路径下的png图片,并将其打印出来。 -- Date :12:49:28 2014-09-04 1 print("Lua Script Start") 2 3 function getFileName( path ) 4 len = string.
823 0
怎么设置阿里云服务器安全组?阿里云安全组规则详细解说
阿里云服务器安全组设置规则分享,阿里云服务器安全组如何放行端口设置教程
6895 0
图灵ios培训第一周(使用UIWebView创建简易浏览器)
       借着给学弟学妹们培训ios的机会,给大家ios新手带来一系列的新手知识博客,希望能给广大ios爱好者以及希望进入ios领域的童鞋们得到帮助。大神路过的请指点。 课前小探索 制作一个简易的浏览器 首先打开Xcode,新建一个工程。
730 0
使用OpenApi弹性释放和设置云服务器ECS释放
云服务器ECS的一个重要特性就是按需创建资源。您可以在业务高峰期按需弹性的自定义规则进行资源创建,在完成业务计算的时候释放资源。本篇将提供几个Tips帮助您更加容易和自动化的完成云服务器的释放和弹性设置。
7746 0
Android PopupWindow使用
1、含义        写的第一篇技术文章还有点小激动,话说popupwindow顾名思义就是类似于对话框样式布局显示,但是却有别于对话框,到底哪里有区别呢,还请客官您细细观看。
693 0
使用 Webix 创建 Email 客户端
Webix 是一个JavaScript UI 库,提供了多达88个UI小部件和功能丰富的 CSS/HTML5 JavaScript 控件。使用 Webix 可以有效地加快 Web 应用的开发。文本将演示了如何通过 Webix 框架,来创建一个 Email 客户端原型。
4709 0
使用IntelliJ IDEA 14和Maven创建java web项目
原文:使用IntelliJ IDEA 14和Maven创建java web项目 http://mark.leanote.com/post/%E4%BD%BF%E7%94%A8IntelliJ-IDEA-14%E5%92%8CMaven%E5%88%9B%E5%BB%BAjava-web%E9%A1%B9%E7%9B%AE 安装Maven 下载安装 去maven官网下载最新版。
1207 0
+关注
641
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
文娱运维技术
立即下载
《SaaS模式云原生数据仓库应用场景实践》
立即下载
《看见新力量:二》电子书
立即下载