Jquery 根据元素的高度和宽度在页面上定位元素

Jquery 根据元素的高度和宽度在页面上定位元素,jquery,css,Jquery,Css,我在这里构建了一个下拉菜单,它使用JSON动态构建菜单。这样做的原因是将HTML放入页面本身是为了提高性能(只加载您需要的内容),这样我就可以将菜单放置在表外 我已经开始实现一种根据菜单的高度和接近窗口(浏览器窗口不是可滚动的容器)来定位菜单的方法。问题是,当菜单的高度大于链接和视口下方的空间时,它应该将菜单移到上方,反之亦然。它的某些部分工作不太正常 注意:如果用户移动窗口等,则在插入HTML后而不是在回调中进行定位的原因是,如果用户滚动或诸如此类的操作,则菜单将被删除,因此这样做没有意义 按

我在这里构建了一个下拉菜单,它使用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();
            });

        });
$(文档).ready(函数(){
$('a.buildMenu')。单击(函数(事件){
//阻止正常行为
event.preventDefault();
//阻止它冒泡到文档
event.stopPropagation();
var-link=$(这个);
//如果菜单已存在,请将其删除并退出请求
if($(document.find('div#')+$(link.data('id')).length){
$('.buildMenu').removeClass('selected');
$('.menu').remove();
返回false;
}
//从DOM中删除任何其他菜单
$('.buildMenu').removeClass('selected');
$('.menu').remove();
//获取链接的位置
var offset=link.offset();
var top=offset.top;
var left=offset.left;
var bottom=top+link.height();
var right=$(window.width()-link.width();
顶部=顶部+连杆高度();
底部=底部+链接高度();
//将菜单附加到DOM的适当位置
var menuInstance=$('loading…).appendTo('body').css({'position':'absolute','top':top','left':left});
//添加实例id
$(menuInstance).attr('id',$(link).data('id');
//将选定的类添加到单击的链接
$(this.addClass('selected');
//请求JSON数据
$.ajax({
url:'menu.json',
超时:5000,
数据类型:“JSON”,
成功:功能(数据){
//构建菜单
var ul=$(“
    ”)attr(“id”,data.menu.id).addClass(data.menu.class); //对于每个菜单项 $.each(data.menu.content.menuitem,函数(){ var li=$(“
  • ”).appendTo(ul.addClass(this.liClass); var anchor=$(“”).appendTo(li).attr(“href”,this.href).attr(“title”,this.title); var span=$(“”).appendTo(anchor).addClass(this.icon).html(this.text) }); //删除加载类并将菜单插入实例 $(menuInstance).removeClass('load').html(ul); //如果菜单高于底部空间 if(menuInstance.height()>底部){ css({'top':'auto','bottom':bottom,'left':left}); } //如果菜单高于顶部空间 else if(menuInstance.height()>top){ css({'top':top,'left':left}); } //默认位置。。。 否则{ css({'top':top,'left':left}); } }, 错误:函数(jqXHR、textStatus、errorshown){ log(jqXHR、textStatus、errorshown); } }); }); //如果单击菜单之外的任何内容,请从DOM中删除菜单 $(文档).bind('click',函数(事件){ var clicked=$(event.target); 如果(!clicked.parents().hasClass('menu')){ $('.buildMenu').removeClass('selected'); $('.menu').remove(); } }); //如果用户滚动面板,则删除菜单 $(窗口).bind('resize',function(){ $('.buildMenu').removeClass('selected'); $('.menu').remove(); }); $('div').bind('scroll',function(){ $('.buildMenu').removeClass('selected'); $('.menu').remove(); }); });
这是问题的屏幕截图(代码应使该菜单显示在链接上方,因为其高度大于链接下方的偏移空间)


看起来问题出在第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
        });
    }

如果你把代码复制到这里就更好了。我对container div的位置不感兴趣,因为菜单可以