根据窗口宽度在Superfish和FlexNav之间切换

时间:2013-09-30 18:38:18

标签: javascript jquery superfish matchmedia

我尝试在一个页面上使用2个jQuery导航脚本(Superfish用于桌面,FlexNav用于移动设备。我目前正在使用matchMedia以及Paul Irish的polyfill来回复CSS3内的JavaScript媒体查询状态更改。

目前的代码仅实现了总体目标的50%。如果您最初访问的网页大小等于或大于999px宽,那么您将获得Superfish,如果您最初访问窗口大小小于999px的网页,则获得FlexNav。当您将窗口调整大小或低于999px时,会发生此问题,因为两个脚本都变为活动状态。

// 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合作,但我愿意接受所有建议。

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

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的销毁功能只是部分破坏它。

2 个答案:

答案 0 :(得分:5)

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

如果我查看Superfish的来源,有一个destroy函数可以执行此操作,但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/

请告诉我这是否适合您!

答案 1 :(得分: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()detach()的使用非常多适合轻松解决您的问题。破坏方式似乎是一个麻烦,很多工作(对于脚本以及当一些用户狂欢与窗口调整大小时)时间损失&对我来说存在许多错误的风险(预计每次破坏时会出现越来越多的滞后现象 - detach()无后顾之忧)

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

专业人士:

  • 脚本将减少工作量从一个切换到另一个

  • 会很快
  • 您可以从中制作一个插件并轻松地将其他菜单插件添加到您的应用中,而无需担心冲突以及如何销毁