在触摸屏上处理悬停事件

时间:2013-12-28 20:09:10

标签: javascript jquery html css responsive-design

我设计的网站使用导航菜单显示子菜单:悬停。初始站点没有使用任何响应式设计:它仅针对桌面环境。我现在使用响应式设计技术来定位移动设备和平板电脑,其中许多是基于触摸而不是基于鼠标。

我面临的一个重大问题(以及许多其他人似乎也面临过)是基于悬停的导航菜单:它在鼠标环境中运行良好,但在触摸设备上,没有可靠的方法来触发悬停,使页面难以使用。

目标是:

  1. 当菜单被鼠标悬停时,显示子菜单。
  2. 使用鼠标单击菜单时,请打开锚标记的链接。
  3. 第一次触摸菜单时,显示子菜单。
  4. 第二次触摸菜单时,打开锚标记的链接。
  5. 为连接了鼠标设备的平板电脑无缝切换功能。
  6. 我的团队不愿意牺牲基于鼠标的机器上的悬停效果。他们喜欢它,不想根据所有设备点击菜单。我同意这一点。

    环顾网后,我找不到任何解决方案。我把它们中的一些放在一起并开发了一些在Android上测试得很好的东西,获得了我想要的功能。有什么可以改进的和/或你看到这种方法有什么问题吗?

    jQuery(document).ready(function() {
        var touched=false;
        jQuery(".nav").on('touchstart', 'li .has_children', function (e) {  touched=true; });
        jQuery("html").on('mousemove', function (e) { touched=false; });
    
        jQuery("html").on('click', updatePreviousTouched );
    
        jQuery(".nav").on('click', 'li .has_children', function (e) {
            updatePreviousTouched(e);
            if( touched ) { 
                if (jQuery(this).data('clicked_once')) {
                    jQuery(this).data('clicked_once', false);
                    return true;
                } else {
                    e.preventDefault();
                    jQuery(this).trigger("mouseenter"); 
                    jQuery(this).data('clicked_once', true);
    
                }
            }
            touched=false;
        }); 
    
        var previous_touched;
        function updatePreviousTouched(e) {
            if( typeof previous_touched != 'undefined' && previous_touched != null && !previous_touched.is( jQuery(e.target) ) ) {
                previous_touched.data('clicked_once', false);
            }
            previous_touched=jQuery(e.target);
        }
    }
    

    这是一个小问题:http://jsfiddle.net/5FfCF/1/

    如果可以改进此解决方案,请提供任何建议。如果您发现它不适合您,请告诉我。我在这里发布它是为了试图获得任何改进建议并发布这个想法,以便其他人可以从中受益。

    以下是我目前测试的结果:

    1. 主流5种浏览器上的Windows 7 :有效。
    2. 默认浏览器上的Android平板电脑:有效。
    3. 在IE和Chrome上使用触摸屏的Windows 7笔记本电脑:工作分类。该机器正在运行两种浏览器的桌面版本,因此它不会触发“touchstart”事件。在触摸屏和浏览器之间的某处,有些东西正在将触摸转换为鼠标事件。但是,由于鼠标是此设备的不可拆卸部分,我不认为这是一个失败。如果它像平板电脑一样工作,我想它,但似乎还没有可用的技术。
    4. iOS iPad :这是之前的我编写上面的javascript。似乎ios在幕后为我们做了一些悬停/点击魔术。我有一个团队成员检查我的javascript是否破坏了iOS功能,我会在得到答案后编辑这篇文章。
    5. 其他说明:

      1. 这只是桌面和平板电脑网站的菜单。移动网站有一个不同的基于点击的菜单。我不建议将此解决方案用于手机大小的设备。

1 个答案:

答案 0 :(得分:13)

Piddle Diddle Fiddle :)


Fiddle Embedded Demo (use with phone for easiest access)


在阅读这一文字墙之前,请检查小提琴并确保它正是您要找的内容。也在手机上测试(我在我的Android上测试过并没有问题)。

如果你有一套完全独立的手机代码,那么你真的无需担心。在iOS设备上适应触摸与悬停事件尤其棘手。但是我能够通过捕获一系列转化为触摸事件的鼠标事件来克服这个问题。

对于您的特定情况,由于您希望三者之间的差别如此,我建议运行早期脚本来获取屏幕大小,如果它小于### px x ### px,则添加一个名为{{1的类或} handheldmobile的任何内容。现在,您只需将body捕获代码分配给touch,然后使用单独的代码将$('.mobile .nav')事件分配给PC。

对于平板电脑,你必须决定什么对你更重要 - 能够使用每个菜单的根菜单项点击和导航,或者只允许点击子菜单项(这将消除需要)将hover类添加到.mobile)。

以下是您应该可以在移动设备和桌面设备上使用的一些代码。

jQuery的:

body

通常情况下,我不会像我将要复制的那样复制所有HTML,但在这个特定的实例中,您需要完全按照我的方式使用它来避免jQuery(document).ready(function () { $('.nav').on('click mousedown mouseup touchstart touchmove', 'a.has_children', function () { if ( $(this).next('ul').hasClass('open') && !$(this).parents('ul').hasClass('open')) { $('.open').removeClass('open'); return false; } $('.open').not($(this).parents('ul')).removeClass('open'); $(this).next('ul').addClass('open'); return false; }); $(document).on('click', ':not(.has_children, .has_children *)', function() { if( $('.open').length > 0 ) { $('.open').removeClass('open'); return false; } }); }); 白色 - 太空故障。将我的小提琴与原作相比较,看看悬停/点击每个链接有多容易。

HTML:

inline-block

很确定我甚至没有碰到CSS所以我现在就把它放在小提琴里。希望这能帮到你。