强制jQuery子菜单导航在mouseout上消失

时间:2012-05-01 16:01:11

标签: jquery menu treeview hover mouseout

我正在为客户建立一个由我的主管设计的网站。在早期,我们决定我们的导航将基于jQuery TreeView菜单(http://www.dynamicdrive.com/dynamicindex1/treeview/index.htm)。

最初,我的主管喜欢TreeView导航的外观和功能。但是在我安装并构建了导航之后,他们改变了主意。现在,他们只想要分支的外观,但具有下拉菜单的基本功能。

我不是jQuery专家,因此我编辑代码非常困难。但是我已经做到了我想做的事 - 只有一个例外。我希望子菜单在mouseout上消失,但它们会一直存在,直到你将鼠标移动到另一个元素。有没有办法用我已经拥有的框架来做到这一点,或者我应该从头开始重建并使其全部基于CSS?

另一个选项是保持每个主导航链接的悬停状态处于活动状态,直到您移动到另一个链接。此时,用作连接分支的背景图像在mouseout上消失,而子菜单则没有。

我基本上只想在子菜单框中显示/消失主菜单项的背景图像。

可在此处查看测试网站:http://tinyurl.com/7novfmc

这是我的CSS:

#navigation a {
color:#666;
text-decoration:none;
}
#navigation a:hover {
color:#C93;
text-decoration:none;
}
.navlink a:hover {
color:#C93;
text-decoration:none;
background-image:url(../images/treeview-horizontal-line.png);
background-repeat:no-repeat;
background-position:right;
padding-right:17px;
}
.treeview, .treeview ul {
padding: 0;
margin: 0;
list-style: none;
}
.treeview ul {
background-color: #FFF;
margin-top: 4px;
}
.treeview .hitarea {
/*background: url(../images/treeview-default.gif) -64px -25px no-repeat;*/
height: 16px;
width: 16px;
margin-left: -16px;
float: left;
cursor: pointer;
}
/* fix for IE6 */
* html .hitarea {
display: inline;
float:none;
}
.treeview li {
margin: 0;
padding: 12px 0pt 16px 16px;
text-transform: lowercase;
font-size: .75em;
}
.treeview a.selected {
background-color: #eee;
}
#treecontrol {
margin: 1em 0;
display: none;
}
.treeview .hover {
color: #C93;
cursor: pointer;
}
.treeview li ul li {
background: url(../images/treeview-orange-line1.png) 0 10px no-repeat;
font-size: 1em;
margin-top:-24px;
}
.treeview li.collapsable, .treeview li.expandable {
background-position: 0 -176px;
}
.treeview .expandable-hitarea {
background-position: -80px -3px;
}
.treeview li.last {
background-position: 0 -1766px
}
.treeview li.lastCollapsable, .treeview li.lastExpandable {
}
.treeview li.lastCollapsable {
background-position: 0 -111px
}
.treeview li.lastExpandable {
background-position: -32px -67px
}
.treeview div.lastCollapsable-hitarea, .treeview div.lastExpandable-hitarea {
background-position: 0;
}
.treeview-famfamfam li {
background-image: url(../images/treeview-famfamfam-line.gif);
}
.treeview-famfamfam .hitarea, .treeview-famfamfam li.lastCollapsable, .treeview-famfamfam li.lastExpandable {
background-image: url(../images/treeview-famfamfam.gif);
}
.filetree li {
padding: 3px 0 2px 16px;
}
.filetree span.folder, .filetree span.file {
padding: 1px 0 1px 16px;
display: block;
}
.filetree span.folder {
background: url(../images/folder.gif) 0 0 no-repeat;
}
.filetree li.expandable span.folder {
background: url(../images/folder-closed.gif) 0 0 no-repeat;
}
.filetree span.file {
background: url(../images/file.gif) 0 0 no-repeat;
}

这是我的HTML(带有一些内联CSS):

            <div id="HEADER_NAVIGATION">
            <div id="MAIN_NAVIGATION">
              <ul id="navigation">
                <li style="margin-left:60px;"><span class="navlink"><a href="about.html">About</a></span>
                    <ul style="margin-left:40px;margin-top:-32px;position:fixed;">
                        <li>Our Approach</li>
                        <li>Experience</li>
                        <li>Global Reach</li>
                    </ul>
                </li>
                <li style="margin-left:75px;"><a href="principals.html">Principals</a></li>
                <li style="margin-left:90px;"><span class="navlink"><a href="offerings.html">Offerings</a></span>
                    <ul style="margin-left:60px;margin-top:-34px;position:fixed;">
                        <li>Performance Improvement</li>
                        <li>Organizational Transformation</li>
                        <li>Solutions Architecture</li>
                        <li>Risk Management</li>
                    </ul>
                </li>
                <li style="margin-left:75px;"><span><a href="testimonials.html">Testimonials</a></span>
                    <ul style="margin-left:70px;margin-top:-3px;position:fixed;">
                        <!--<li>Case Studies</li>-->
                    </ul>
                </li>
                <li style="margin-left:60px;"><span class="navlink"><a href="resources.html">Resources</a></span>
                    <ul style="margin-left:65px;margin-top:-13px;position:fixed;">
                        <li>Strategic Alliances</li>
                        <li>Publications</li>
                    </ul>
                </li>
            </ul>
            </div>
            <div id="MAIN_HEADER_IMAGE"></div>
        </div>

这是我的jquery:

$(document).ready(function(){

// first example
$("#navigation").treeview({
    collapsed: true,
    unique: true,
    persist: "location"
});
});

;(function($) {

$.extend($.fn, {
    swapClass: function(c1, c2) {
        var c1Elements = this.filter('.' + c1);
        this.filter('.' + c2).removeClass(c2).addClass(c1);
        c1Elements.removeClass(c1).addClass(c2);
        return this;
    },
    replaceClass: function(c1, c2) {
        return this.filter('.' + c1).removeClass(c1).addClass(c2).end();
    },
    hoverClass: function(className) {
        className = className || "hover";
        return this.hover(function() {
            $(this).addClass(className);
        }, function() {
            $(this).removeClass(className);
        });
    },
    heightToggle: function(animated, callback) {
        animated ?
            this.animate({ height: "toggle" }, animated, callback) :
            this.each(function(){
                jQuery(this)[ jQuery(this).is(":hidden") ? "show" : "show" ](); // default here is "show" : "hide"
                if(callback)
                    callback.apply(this, arguments);
            });
    },
    heightHide: function(animated, callback) {
        if (animated) {
            this.animate({ height: "hide" }, animated, callback);
        } else {
            this.hide();
            if (callback)
                this.each(callback);                
        }
    },
    prepareBranches: function(settings) {
        if (!settings.prerendered) {
            // mark last tree items
            this.filter(":last-child:not(ul)").addClass(CLASSES.last);
            // collapse whole tree, or only those marked as closed, anyway except those marked as open
            this.filter((settings.collapsed ? "" : "." + CLASSES.closed) + ":not(." + CLASSES.open + ")").find(">ul").hide();
        }
        // return all items with sublists
        return this.filter(":has(>ul)");
    },
    applyClasses: function(settings, toggler) {
        this.filter(":has(>ul):not(:has(>a))").find(">span").hover(function(event) {
            toggler.apply($(this).next());
        }).add( $("a", this) ).hoverClass();

        if (!settings.prerendered) {
            // handle closed ones first
            this.filter(":has(>ul:hidden)")
                    .addClass(CLASSES.expandable)
                    .replaceClass(CLASSES.last, CLASSES.lastExpandable);

            // handle open ones
            this.not(":has(>ul:hidden)")
                    .addClass(CLASSES.collapsable)
                    .replaceClass(CLASSES.last, CLASSES.lastCollapsable);

            // create hitarea
            this.prepend("<div class=\"" + CLASSES.hitarea + "\"/>").find("div." + CLASSES.hitarea).each(function() {
                var classes = "";
                $.each($(this).parent().attr("class").split(" "), function() {
                    classes += this + "-hitarea ";
                });
                $(this).addClass( classes );
            });
        }

        // apply event to hitarea
        this.find("div." + CLASSES.hitarea).mouseout( toggler );
    },
    treeview: function(settings) {

        settings = $.extend({
            cookieId: "treeview"
        }, settings);

        if (settings.add) {
            return this.trigger("add", [settings.add]);
        }

        if ( settings.toggle ) {
            var callback = settings.toggle;
            settings.toggle = function() {
                return callback.apply($(this).parent()[0], arguments);
            };
        }

        // factory for treecontroller
        function treeController(tree, control) {
            // factory for click handlers
            function handler(filter) {
                return function() {
                    // reuse toggle event handler, applying the elements to toggle
                    // start searching for all hitareas
                    toggler.apply( $("div." + CLASSES.hitarea, tree).filter(function() {
                        // for plain toggle, no filter is provided, otherwise we need to check the parent element
                        return filter ? $(this).parent("." + filter).length : true;
                    }) );
                    return false;
                };
            }
            // click on first element to collapse tree
            $("a:eq(0)", control).click( handler(CLASSES.collapsable) );
            // click on second to expand tree
            $("a:eq(1)", control).click( handler(CLASSES.expandable) );
            // click on third to toggle tree
            $("a:eq(2)", control).click( handler() ); 
        }

        // handle toggle event
        function toggler() {
            $(this)
                .parent()
                // swap classes for hitarea
                .find(">.hitarea")
                    .swapClass( CLASSES.collapsableHitarea, CLASSES.expandableHitarea )
                    .swapClass( CLASSES.lastCollapsableHitarea, CLASSES.lastExpandableHitarea )
                .end()
                // swap classes for parent li
                .swapClass( CLASSES.collapsable, CLASSES.expandable )
                .swapClass( CLASSES.lastCollapsable, CLASSES.lastExpandable )
                // find child lists
                .find( ">ul" )
                // toggle them
                .heightToggle( settings.animated, settings.toggle );
            if ( settings.unique ) {
                $(this).parent()
                    .siblings()
                    // swap classes for hitarea
                    .find(">.hitarea")
                        .replaceClass( CLASSES.collapsableHitarea, CLASSES.expandableHitarea )
                        .replaceClass( CLASSES.lastCollapsableHitarea, CLASSES.lastExpandableHitarea )
                    .end()
                    .replaceClass( CLASSES.collapsable, CLASSES.expandable )
                    .replaceClass( CLASSES.lastCollapsable, CLASSES.lastExpandable )
                    .find( ">ul" )
                    .heightHide( settings.animated, settings.toggle );
            }
        }

        function serialize() {
            function binary(arg) {
                return arg ? 1 : 0;
            }
            var data = [];
            branches.each(function(i, e) {
                data[i] = $(e).is(":has(>ul:visible)") ? 1 : 0;
            });
            $.cookie(settings.cookieId, data.join("") );
        }

        function deserialize() {
            var stored = $.cookie(settings.cookieId);
            if ( stored ) {
                var data = stored.split("");
                branches.each(function(i, e) {
                    $(e).find(">ul")[ parseInt(data[i]) ? "show" : "hide" ]();
                });
            }
        }

        // add treeview class to activate styles
        this.addClass("treeview");

        // prepare branches and find all tree items with child lists
        var branches = this.find("li").prepareBranches(settings);

        switch(settings.persist) {
        case "cookie":
            var toggleCallback = settings.toggle;
            settings.toggle = function() {
                serialize();
                if (toggleCallback) {
                    toggleCallback.apply(this, arguments);
                }
            };
            deserialize();
            break;
        case "location":
            var current = this.find("a").filter(function() { return this.href.toLowerCase() == location.href.toLowerCase(); });
            if ( current.length ) {
                current.addClass("selected").parents("ul, li").add( current.next() ).show();
            }
            break;
        }

        branches.applyClasses(settings, toggler);

        // if control option is set, create the treecontroller and show it
        if ( settings.control ) {
            treeController(this, settings.control);
            $(settings.control).show();
        }

        return this.bind("add", function(event, branches) {
            $(branches).prev()
                .removeClass(CLASSES.last)
                .removeClass(CLASSES.lastCollapsable)
                .removeClass(CLASSES.lastExpandable)
            .find(">.hitarea")
                .removeClass(CLASSES.lastCollapsableHitarea)
                .removeClass(CLASSES.lastExpandableHitarea);
            $(branches).find("li").andSelf().prepareBranches(settings).applyClasses(settings, toggler);
        });
    }
});

// classes used by the plugin
// need to be styled via external stylesheet, see first example
var CLASSES = $.fn.treeview.classes = {
    open: "open",
    closed: "closed",
    expandable: "expandable",
    expandableHitarea: "expandable-hitarea",
    lastExpandableHitarea: "lastExpandable-hitarea",
    collapsable: "collapsable",
    collapsableHitarea: "collapsable-hitarea",
    lastCollapsableHitarea: "lastCollapsable-hitarea",
    lastCollapsable: "lastCollapsable",
    lastExpandable: "lastExpandable",
    last: "last",
    hitarea: "hitarea"
};

// provide backwards compability
$.fn.Treeview = $.fn.treeview;

})(jQuery);

感谢您的帮助!

1 个答案:

答案 0 :(得分:0)

您不需要该树视图插件来执行您需要的操作。

添加到css

#navigation ul { display: none; }
#navigation li.hover ul { display: block; }

将jquery更改为

$(document).ready(function(){
    $('#navigation>li').hover(
        function() { $(this).addClass('hover'); },
        function() { $(this).removeClass('hover'); }
    );
});

结果http://jsfiddle.net/J3Khk/

您也可以使用普通css并使用

将javascript全部丢弃
#navigation ul { display: none; }
#navigation li:hover ul { display: block; }

结果http://jsfiddle.net/cBf3c/

编辑:如果您仅使用插件进行树视图行,则也可以使用css执行此操作。您可以使用背景图片,或者如果您足够聪明,可以使用一些绝对定位的<hr />