4

我正在尝试jQuery在一页上使用 2 个导航脚本(Superfish用于台式机和FlexNav 移动设备)。我目前matchMedia与 Paul Irish 一起使用来polyfill响应.CSS3JavaScript

当前的代码只完成了总体目标的 50%。如果您最初使用等于或大于 999px 宽的窗口大小访问网页,那么您会得到Superfish,如果您最初使用小于 999px 的窗口大小访问网页,那么您会得到FlexNav. 当您将窗口大小调整为高于或低于 999 像素时,会出现此问题,因为这两个脚本都处于活动状态。

// media query event handler
if (matchMedia) {
    var mq = window.matchMedia("(min-width: 999px)");
    mq.addListener(WidthChange);
    WidthChange(mq);
}
// media query change
function WidthChange(mq) {
    if (mq.matches) {
        $("ul.sf-menu").superfish({
            delay: 350,
            speed: 400,
        });
    } else {
        $("ul.flexnav").flexNav({
            'animationSpeed': '250',
            'transitionOpacity': true,
            'buttonSelector': '.menu-button',
            'hoverIntent': false
        });
    }
}

尽管我很想与它一起工作matchMedia,但我对所有建议持开放态度。

更新:感谢斯蒂芬的建议,我现在有以下代码:

jQuery(document).ready(function () {
    // add destroy function for FlexNav
    flexNavDestroy = function () {
        $('.touch-button').off('touchstart click').remove();
        $('.item-with-ul *').off('focus');
    }
    // media query event handler
    if (matchMedia) {
        var mq = window.matchMedia("(min-width: 999px)");
        mq.addListener(WidthChange);
        WidthChange(mq);
    }
    // media query change

    function WidthChange(mq) {
        if (mq.matches) {
            if (typeof (flexNav) != "undefined") {
                flexNavDestroy();
            }
            superfish = $("ul.sf-menu").superfish({
                delay: 350,
                speed: 400,
            });
        } else {
            if (typeof (superfish) != "undefined") {
                superfish.superfish('destroy');
            }
            flexNav = $("ul.flexnav").flexNav({
                'animationSpeed': '250',
                'transitionOpacity': true,
                'buttonSelector': '.menu-button',
                'hoverIntent': false
            });
        }
    }
});

剩余问题: 的销毁功能FlexNav只是部分销毁它。

4

2 回答 2

5

最好的方法可能是在您激活一个插件时销毁另一个插件。

如果我查看Superfish的源代码,有一个破坏函数可以执行此操作,但 flexNav 没有这样的功能。您可以创建一个:

flexNavDestroy = function(){
    $('.touch-button').off('touchstart click').remove();
    $(('.item-with-ul *').off('focus');
}

然后你可以这样做:

function WidthChange(mq) {
    if (mq.matches) {
        if(typeof(flexNav) != "undefined") {
            flexNavDestroy();
        }

        superfish = $("ul.sf-menu").superfish({
            delay: 350,
            speed: 400,
        });
    } else {
        if(typeof(superfish) != "undefined") {
            superfish.superfish('destroy'); 
        }

        flexNav = $("ul.flexnav").flexNav({
            'animationSpeed': '250',
            'transitionOpacity': true,
            'buttonSelector': '.menu-button',
            'hoverIntent': false
        });
    }
}

更新 我对 FlexNav 进行了更多研究,但我错过了一些事情。

我认为样式是冲突的,因为 FlexNav 默认设置了很多样式。我们可以通过使用两个类来轻松防止这种情况:一个用于 flexnav 样式(默认.flexnav),我们可以删除它以隐藏它的所有样式,另一个用于绑定 javascript 函数(它将始终保留在那里,或者我们无法重新附加它)。

我通常喜欢在任何作为 JS 钩子的类前面加上js-,所以在我的示例(如下)中,我将.flexnav菜单上的类替换为.js-flexnav. 然后要激活 flexnav,您必须在调用之前添加此行$('ul.flexnav').flexNav()

$('.js-flexnav').addClass('flexnav');

在destroy 函数中,您将不得不再次删除该类,我将在稍后展示。

此外,我不确定 Superfish 是如何显示和隐藏的,但由于 FlexNav 会折叠所有子菜单,因此可以肯定地说您应该重新显示它们,以便 Superfish 可以自己做。

更新的销毁函数以反映这一点:

function flexNavDestroy(){
    $('.touch-button').off('touchstart click').remove();
    $('.item-with-ul *').off('focus');
    $('.js-flexnav').removeClass('flexnav').find('ul').show(); // removes .flexnav for styling, then shows all children ul's
}

这是一个 jsFiddle,显示使用新代码激活/停用 flexNav:http: //jsfiddle.net/9HndJ/

让我知道这是否对您有用!

于 2013-09-30T21:55:13.970 回答
1

这是一条替代路径:

页面加载后:

将菜单缓存在 jquery 对象中,克隆它 并在每个克隆上实例化两个插件

$menucontainer= $("#menu_container");
$memufish = $menucontainer.find(".menu");
$menuflex=$menufish.clone();

$menufish.superfish().detach();
$menuflex.prependTo($menucontainer).flexnav().detach(); 

(它们无论如何都会被加载,所以即使大部分时间不需要它也没什么大不了的,它会在那里并准备好以防万一 - 但是测试你是否可以在不将其附加到 DOM 的情况下实例化克隆)

取决于宽度附加/前置所需的一个

$menuflex.prependTo($menucontainer);    

在改变宽度时分离一个重新连接另一个

$menufish.detach();
$menuflex.prependTo($menucontainer);

你也可以按照自己的方式检查插件是否在宽度变化时被实例化(为了不实例化无用的onload),但无论如何我相信使用clone()anddetach()非常适合轻松解决你的问题。销毁方式似乎很麻烦,需要大量工作(对于脚本以及当某些用户对窗口调整大小赞不绝口时)浪费时间和对我来说存在许多错误的风险(预计每次销毁重新实例化时会出现越来越多的滞后 -不用detach()担心)

缺点:将使用更多的内存大修

优点:

  • 脚本的工作量会减少,并且从一个切换到另一个会非常快

  • 您可以从中制作插件并将其他菜单插件添加到您的应用程序中,无需担心冲突和如何销毁

于 2013-10-09T07:38:22.957 回答