定位上下文菜单

12

我正在尝试使用jQuery定位自定义上下文菜单。 第一次它出现在正确的位置(鼠标坐标),但是之后当前位置会与新位置相加,使得菜单消失在屏幕之外。 以下是JavaScript代码:

<script>
$(function(){
    $('#box').hide();

    $(document).bind("contextmenu", function(e) {
        $("#box").offset({left:e.pageX, top:e.pageY});
        $('#box').show();
        e.preventDefault();
    });

    $(document).bind("click", function(e) {
        $('#box').hide();
    });
    $('#box').bind("click", function(e) {
        $('#box').hide();
    });
});
</script>

顺便说一下,最近版本的jQuery中,.on()已经取代了.bind() - Blazemonger
4个回答

11
尝试使用position: fixed;,其中上下文菜单的位置根据以下条件更改 -
var windowHeight = $(window).height()/2;
var windowWidth = $(window).width()/2;
if(e.clientY > windowHeight && e.clientX <= windowWidth) {
  $("#contextMenuContainer").css("left", e.clientX);
  $("#contextMenuContainer").css("bottom", $(window).height()-e.clientY);
  $("#contextMenuContainer").css("right", "auto");
  $("#contextMenuContainer").css("top", "auto");
} else if(e.clientY > windowHeight && e.clientX > windowWidth) {
  $("#contextMenuContainer").css("right", $(window).width()-e.clientX);
  $("#contextMenuContainer").css("bottom", $(window).height()-e.clientY);
  $("#contextMenuContainer").css("left", "auto");
  $("#contextMenuContainer").css("top", "auto");
} else if(e.clientY <= windowHeight && e.clientX <= windowWidth) {
  $("#contextMenuContainer").css("left", e.clientX);
  $("#contextMenuContainer").css("top", e.clientY);
  $("#contextMenuContainer").css("right", "auto");
  $("#contextMenuContainer").css("bottom", "auto");
} else {
  $("#contextMenuContainer").css("right", $(window).width()-e.clientX);
  $("#contextMenuContainer").css("top", e.clientY);
  $("#contextMenuContainer").css("left", "auto");
  $("#contextMenuContainer").css("bottom", "auto");
}

http://jsfiddle.net/AkshayBandivadekar/zakn7Lwb/14/


2
这正是我在寻找的!谢谢。 - Genarito

8
不要使用offset方法,尝试使用css代替,在绝对定位上下文菜单:
$("#box").css({left:e.pageX, top:e.pageY});

CSS(层叠样式表):
#box {
    ...
    position: absolute;
}

http://jsfiddle.net/smxLk/


无论如何,我实际上更喜欢这种方式。在我看来,正确理解CSS并相应地设置它总是比使用jQuery更好,但我会做一个修正。我会使用“fixed”而不是“absolute”。这样它就不会受到非静态父级的影响,也不会引起滚动条。 - Joseph Marikle
1
@JosephMarikle 使用 position: fixed 会使上下文菜单在长页面内容的页面上表现奇怪:http://jsfiddle.net/smxLk/1/。`position:absolute` 可以正常工作:http://jsfiddle.net/smxLk/2/。 我认为在显示之前,我们必须检查菜单是否超出屏幕并相应地修复其位置,否则如果被裁剪,菜单就没有意义了。 - dfsq
好的,我忘记了当你使用 position:fixed 滚动时它会停留在一个位置。XD - Joseph Marikle
当 #box 容器有任何边距或在 #box 之前有任何其他内容放置时,它将无法正常工作。 - Vladimir Topolev

6
问题在于,当您右键单击,然后在其他地方左键单击,然后再次右键单击时,位置不正确。
问题的根源在于,在显示元素之前设置偏移量。如果元素设置为display:none,然后更改其偏移量,似乎会混淆jQuery。
要解决问题,您需要在代码中交换showoffset行。
$(document).bind("contextmenu", function(e) {
    $("#box").offset({left:e.pageX, top:e.pageY});
    $('#box').show();
    e.preventDefault();
});

变成

$(document).bind("contextmenu", function(e) {
    $('#box').show();
    $("#box").offset({left:e.pageX, top:e.pageY});
    e.preventDefault();
});

演示

源代码


那么这是jQuery的错误吗? - Blazemonger
@Blazemonger 或许吧。但我不确定它会被修复,因为更改隐藏元素的偏移量并没有太多意义。但很遗憾,我对此没有明确的答案。 - Joseph Marikle

0
我使用jQuery编写了这段代码来定位我的上下文菜单。
$('body').contextmenu(function (e){
    e.preventDefault();
    let locationX = e.clientX;
    let locationY = e.clientY;
    let ContextWidth = $('#context').width();
    let ContextHeight = $('#context').height();
    let windowWidth = $(window).outerWidth();
    let windowHeight = $(window).outerHeight();

    if (locationY + ContextHeight > windowHeight){
        locationY -= ContextHeight;
    }
    if (locationX + ContextWidth > windowWidth){
        locationX -= ContextWidth;
    };

    $('#context').fadeIn().css({'left': locationX + 'px', 'top': locationY + 'px'});
});

如果你想使用这个,你需要写这个CSS样式:#context {position: fixed; left: 0; top: 0; display: none;}


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接