页面上的位置元素基于其高度和宽度

时间:2012-03-26 13:10:10

标签: jquery css

我在这里构建了一个下拉菜单http://dev.driz.co.uk/jsonmenu/,它使用JSON动态构建菜单。将HTML放入页面本身的这种做法的原因在于性能(仅加载你需要的东西),以便我可以将菜单放在表格之外。

我已经开始实现一种基于菜单高度和窗口附近(浏览器窗口而不是可滚动容器)定位菜单的方法。问题是,当菜单的高度大于链接和视口下方的空间时,它应该移动上面的菜单,反之亦然。部分工作不太正常。

注意:如果用户移动窗口等,在插入HTML后而不是在回调中完成定位的原因是因为如果用户滚动或类似的东西,则删除菜单,这样做就没有意义了

所要求的代码:

        $(document).ready(function () {

            $('a.buildMenu').click(function (event) {

                // Prevent normal behaviour
                event.preventDefault();

                // Stops it bubbling to the document
                event.stopPropagation();

                var link = $(this);

                // If the menu already exists remove it and exit the request
                if($(document).find('div#' + $(link).data('id')).length){
                    $('.buildMenu').removeClass('selected');
                    $('.menu').remove();
                    return false;
                }

                // Remove any other menus from the DOM
                $('.buildMenu').removeClass('selected');
                $('.menu').remove();

                // Get the position of the link
                var offset = link.offset();
                var top = offset.top;
                var left = offset.left; 
                var bottom = top + link.height();
                var right = $(window).width() - link.width();

                top = top + link.height();

                bottom = bottom + link.height();

                // Append the menu to the DOM in position
                var menuInstance = $('<div class="menu loading">loading...</div>').appendTo('body').css({'position':'absolute','top':top,'left':left});

                // Add the instance id
                $(menuInstance).attr('id', $(link).data('id'));

                // Add class of selected to clicked link
                $(this).addClass('selected');

                // Request JSON data        
                $.ajax({
                    url: 'menu.json',
                    timeout: 5000,
                    dataType: 'JSON',
                    success: function (data) {

                        // Build the menu
                        var ul = $("<ul/>").attr("id", data.menu.id).addClass(data.menu.class);

                        // For each menu item
                        $.each(data.menu.content.menuitem, function () {
                            var li = $("<li/>").appendTo(ul).addClass(this.liClass);
                            var anchor = $("<a/>").appendTo(li).attr("href", this.href).attr("title", this.title);
                            var span = $("<span/>").appendTo(anchor).addClass(this.icon).html(this.text)
                        });

                        // Remove the loading class and insert menu into instance
                        $(menuInstance).removeClass('loading').html(ul);

                        // If the menu is taller than the bottom space
                        if(menuInstance.height() > bottom) {
                            menuInstance.css({'top':'auto','bottom':bottom,'left':left});
                        }
                        // If the menu is taller than the top space
                        else if(menuInstance.height() > top) {
                            menuInstance.css({'top':top,'left':left});
                        }
                        // Default position...
                        else {
                            menuInstance.css({'top':top,'left':left});
                        }

                    },
                    error: function (jqXHR, textStatus, errorThrown) {
                        console.log(jqXHR, textStatus, errorThrown);
                    }
                });

            });

            // Remove menu from DOM if anything except the menu is clicked
            $(document).bind('click', function (event) {
                var clicked = $(event.target);
                if (!clicked.parents().hasClass('menu')) {
                    $('.buildMenu').removeClass('selected');
                    $('.menu').remove();
                }
            });

            // Remove menu if user scrolls panel
            $(window).bind('resize', function() {   
                $('.buildMenu').removeClass('selected');
                $('.menu').remove();
            });

            $('div').bind('scroll', function() {    
                $('.buildMenu').removeClass('selected');
                $('.menu').remove();
            });

        });

以下是该问题的屏幕截图(代码应该使该菜单显示在链接上方,因为它的高度大于链接下方的偏移空间)

enter image description here

1 个答案:

答案 0 :(得分:1)

看起来问题出在第71-74行。

// If the menu is taller than the bottom space
if(menuInstance.height() > bottom) {
      menuInstance.css({'top':'auto','bottom':bottom,'left':left});
}

bottom被计算为从窗口顶部到菜单链接底部的距离......并且您说“如果菜单高度大于那个”。

我认为您要检查的是菜单高度是否大于从菜单链接底部到窗口底部的距离。所以......

    if(menuInstance.height() > ($(window).height() - bottom) )

这应该是从链接底部到窗口底部的距离,并将其与菜单的高度进行比较。

然后你需要纠正你的位置menuInstance

    'bottom': ($(window).height() - top) + link.height()

这是完整的代码......

    // If the menu is taller than the bottom space
    if (menuInstance.height() > ($(window).height() - bottom)) {
        menuInstance.css({
            'top': 'auto',
            'bottom': ($(window).height() - top) + link.height(),
            'left': left
        });
    }