jQuery UI对话框固定定位

42

我需要对话框即使在页面滚动时仍保持固定位置,所以我使用了http://forum.jquery.com/topic/dialog-position-fixed-12-1-2010上的扩展程序,但是它存在两个问题:

  • 在IE和Firefox上页面滚动时会闪烁(在Safari/Chrome中则没有问题)

  • 关闭并重新打开后,它就失去了粘性并随着页面一起滚动。

这是我用于创建对话框的代码:

$('<div id="'+divpm_id+'"><div id="inner_'+divpm_id+'"></div><textarea class="msgTxt" id="txt'+divpm_id+'" rows="2"></textarea></div>')
                .dialog({
                autoOpen: true,
                title: user_str,
                height: 200,
                stack: true,
                sticky: true //uses ui dialog extension to keep it fixed
     });

以下是我重新打开它所使用的代码:

jQuery('#'+divpm_id).parent().css('display','block');

有什么建议/解决方案吗?

谢谢


如果您知道另一个jQuery插件,用于固定对话框并且不会闪烁,我也很感兴趣。 - scc
15个回答

46

我尝试了这里发布的一些解决方案,但是如果在打开对话框之前已经滚动页面,则它们无法工作。问题在于在计算位置时没有考虑滚动位置,因为此时位置是绝对的。

我发现的解决方案是在打开对话框之前将对话框的父CSS设置为fixed。

$('#my-dialog').parent().css({position:"fixed"}).end().dialog('open');

假设您已将对话框初始化为autoOpen设置为false。

请注意,如果对话框是可调整大小的,则此方法不起作用。必须禁用调整大小才能使位置保持固定。

$('#my-dialog').dialog({ autoOpen: false, resizable: false });

已经彻底测试了,目前没有发现任何错误。


9
我认为最好在创建事件中运行此逻辑,这样您可以在其他地方调用标准的.dialog('open'),而无需每次都运行此 hack... $('#metadata').dialog({ create: function (event) { $(event.target).parent().css('position', 'fixed'); }); - Langdon
2
将dialogClass设置为一个带有position:fixed的类在1.8.24中是有效的,但自从1.9.0以后,在打开之前向下滚动会导致其偏离屏幕。 - Omu
1
Scott的答案在jQuery-UI 1.11上运行良好。对@Langdon评论的一个小改进:使用$("selector").dialog("widget")使您更加健壮,以应对未来jQuery对话框DOM结构的更改。所以就变成了:$('#metadata').dialog({ create: function(event) { $(event.target).dialog("widget").css({ "position": "fixed" }); }); - Stefan Haberl

33

我结合了一些建议的解决方案来修改以下代码。 在Chrome、Firefox和IE9中,滚动、移动和调整大小都能正常工作。

$(dlg).dialog({
    create: function(event, ui) {
        $(event.target).parent().css('position', 'fixed');
    },
    resizeStop: function(event, ui) {
        var position = [(Math.floor(ui.position.left) - $(window).scrollLeft()),
                         (Math.floor(ui.position.top) - $(window).scrollTop())];
        $(event.target).parent().css('position', 'fixed');
        $(dlg).dialog('option','position',position);
    }
});

更新:

如果您想将其设置为所有对话框的默认值:

$.ui.dialog.prototype._oldinit = $.ui.dialog.prototype._init;
$.ui.dialog.prototype._init = function() {
    $(this.element).parent().css('position', 'fixed');
    $(this.element).dialog("option",{
        resizeStop: function(event,ui) {
            var position = [(Math.floor(ui.position.left) - $(window).scrollLeft()),
                            (Math.floor(ui.position.top) - $(window).scrollTop())];
            $(event.target).parent().css('position', 'fixed');
            // $(event.target).parent().dialog('option','position',position);
            // removed parent() according to hai's comment (I didn't test it)
            $(event.target).dialog('option','position',position);
            return true;
        }
    });
    this._oldinit();
};

这对我来说似乎是最完整的解决方案,非常有效 - 谢谢。 - danmux
请在更新部分的第一行中删除.parent()$(event.target).parent().dialog('option','position',position); - hai
这个真的帮我省了很多麻烦!谢谢! - v3nt
谢谢!!!使用旧版本的jQuery UI(1.8.7)真是帮了我大忙。 - space_balls
这个功能表现得相当不错,除了在调整大小时该框消失了。 - mpen
显示剩余2条评论

10

我无法使用jQuery UI 1.9.1来实现Scott的答案。我的解决方案是在open事件的回调函数中重新定位对话框。首先将css位置设置为fixed,然后将对话框定位到所需位置:

$('selector').dialog({
    autoOpen: false,
    open: function(event, ui) {
        $(event.target).dialog('widget')
            .css({ position: 'fixed' })
            .position({ my: 'center', at: 'center', of: window });
    },
    resizable: false
});

注意:如另一个答案中所指出的那样,调整对话框大小会再次将其位置设置为 absolute,因此我已禁用了 resizable


8

根据Langdons's上面的评论,我尝试了以下内容,在jQuery-UI 1.10.0和可调整大小的对话框中运行良好:

$('#metadata').dialog(
{
    create: function (event) {
    $(event.target).parent().css('position', 'fixed'); 
    },
    resizeStart: function (event) {
    $(event.target).parent().css('position', 'fixed'); 
    },
    resizeStop: function (event) {
    $(event.target).parent().css('position', 'fixed'); 
    }
});

这是唯一可靠的方法。 - torvin

4
尝试:
$(document).ready(function() {
  $('#myDialog').dialog({dialogClass: "flora"});
  $('.flora.ui-dialog').css({position:"fixed"});
)};

(from http://dev.jqueryui.com/ticket/2848)


假定您正在使用jqueryui.com的对话框。 - kingjeffrey
如果用户在滚动后打开对话框,这将无法正常工作。问题在于jQuery的对话框计算对话框位置相对于窗口滚动偏移量,而这对于position:fixed是不需要的。我会在找到解决方法后发布更新(而不是分叉源代码)。 - Scott Greenfield
1
呵呵。刚刚谷歌了一下如何做这个,结果找到了自己的答案!有点奇怪。 - kingjeffrey
刚刚发布了一个解决方案,和你的非常相似,但修复了我在之前评论中描述的 bug。 - Scott Greenfield

3

使用CSS强制对话框的位置为 position:fixed

$('.selector').dialog({ dialogClass: 'myPosition' });

并将 myPosition CSS 类定义为:

.myPosition {
    position: fixed;
}

2
$("#myDilog").dialog({
    create:function(){
        $(this).parent().css({position:"fixed"});
    }
});

1
尽管此代码片段可能解决问题,但包括解释确实有助于提高您的帖子质量。请记住,您正在为将来的读者回答问题,这些人可能不知道您的代码建议原因。 - zondo

1

我发现这些答案对我没有用,但是将它们结合起来使用确实有效。 我使用create函数将对话框设置为固定的,这样在创建对话框时它不会滚动窗口。

create: function (event) { 
        $(event.target).parent().css('position', 'fixed')
    }

我使用了open函数来确保对话框不会因为更改顶部值而消失在屏幕上。
open: function(event, ui) {
        $(event.target).parent().css('top', '30%')
    }

这个使用了autoOpen和resizable。


0
$('#'+tweetidstack.pop()).dialog("open").parent().css({position:"fixed"});

为什么要使用 $(document).ready?这可能是最近的发展,但现在它运行良好。

通过这样做,每次打开对话框时都会设置CSS属性。如果你在文档准备好时设置它,那么它只会设置一次,并且适用于所有未来的打开操作。 - kingjeffrey

0

正如我在博客https://xbrowser.altervista.org/informatica-portata/jquery-easyui-bug-fix-window-dialog-position-widget/中所写的, 我发现了“窗口”元素或“对话框”元素中的一个错误。 当您实例化此小部件时,它会超出主浏览器窗口,特别是在拖动或调整大小时的顶部和左侧位置。 为了解决这个问题,我实现了以下解决方案。

您可以在下面阅读源代码:

$(dialog).window({
   onMove: function(left, top) {
   if (left < 0 || top < 0) {
     left = (left < 0) ? 0 : left;
     top = (top < 0) ? 0 : top;
     $(this).window('move', {left: left, top: top});
   }
},
onResize: function(width, height) {
  var opt = $(this).window("options");
  var top = opt.top;
  var left = opt.left;
  if (top < 0) {
    top = (top < 0) ? 0 : top;
    $(this).window('move', {left: left, top: top});
  }
}
}).window("open");

The same code is for dialog:

$(dialog).dialog({
  onMove: function(left, top) {
  if (left < 0 || top < 0) {
     left = (left < 0) ? 0 : left;
     top = (top < 0) ? 0 : top;
     $(this).dialog('move', {left: left, top: top});
  }
},
onResize: function(width, height) {
   var opt = $(this).window("options");
   var top = opt.top;
   var left = opt.left;
   if (top < 0) {
     top = (top < 0) ? 0 : top;
     $(this).dialog('move', {left: left, top: top});
   }
}
}).dialog("open");

此外,在“onResize”方法中调用“$(this).window(“options”);”并启动您的应用程序时,您看不到窗口;因此,我必须在对话框声明的末尾插入“.window(“open”);”。
希望能帮到您。

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