JQuery UI 的可调整大小不支持 position: fixed; 有什么建议吗?

14

JQuery UI的.resizable函数不支持position: fixed;元素。一旦您尝试调整它们的大小,它会将它们的位置属性切换到absolute。有什么推荐的解决方法吗?

我有一些聊天窗口,可以在文档中拖动。它们的位置是固定的,这样它们就不会随着后面的页面滚动。它们都完美地工作,直到您尝试调整某个窗口的大小,那时它会转换为position: absolute;,并被留在页面滚动后面。

我尝试处理调整大小停止事件并将位置更改为fixed:

    stop: function (event, ui)
    {
        $(chatWindow).css('position', 'fixed');
    }

这不起作用是因为固定元素的定位(top:left:)不正确,当你停止调整大小时,元素会切换到固定定位并跳到页面上奇怪的位置。有时会跳出页面边界并永久丢失。

有什么建议吗?


如果把它放在一个固定的容器里面呢?(我还没有测试过) - Paul
把它放在一个固定在0 0位置的容器里怎么样? - Paul
7个回答

11
为了解决这个问题,我用 .draggable() 包装了 .resizable() 块:
<div id="draggable-dealie">
    <div id="resizable-dealie">
    </div>
</div>

相应的JavaScript代码:

$("#draggable-dealie").draggable();
$("#resizable-dealie").resizable();

确保您在 #draggable-dealie CSS 中设置了 position:fixed !important; 属性:

#draggable-dealie {
    position:fixed !important;
    width:auto;
    height:auto;
}

我有一个演示,地址为:http://jsfiddle.net/smokinjoe/FfRRW/8/


1
太棒了!这是一个更好的解决方案。JQuery UI只需要修复这个问题,这样你就可以在单个固定元素上同时使用它们,但在那之前,这是我见过的最优雅的解决方案。 - Chev
1
重要的部分解决了我的问题,为我节省了很多工作。谢谢。 - xsl
2
硬编码顶部/左侧并使用!important解决了我的问题。虽然不太美观,但我会接受它,因为要么这样做,要么重新实现可调整大小的逻辑。 - Mahn

6

如果和我一样,你在页面底部有一个固定的div,那么你可以在这些css规则后面添加!important,使其保持在底部:

.fixed {
  position: fixed !important;
  top: auto !important;
  bottom: 0 !important;
  left: 0;
  right: 0;
}

只需通过其北边框使其可调整大小:

$('.fixed').resizable({
  handles: "n"
});

这应该是被接受的答案,因为它只使用CSS,而不需要HTML和JS的开销。 - Nick Mitchell

3

当调整大小开始和结束时,只需在元素上强制使用position:fixed。

$(".e").draggable().resizable({
   start: function(event, ui) {
      $(".e").css("position", "fixed");
   },
   stop: function(event, ui) {
      $(".e").css("position", "fixed");
   }
});

JSFiddle: http://jsfiddle.net/5feKU/(网站名称)

2

这是我想出的解决方案,虽然代码有点多,但它可以解决问题:

$("#test").resizable({stop:function(e, ui) {
    var pane = $(e.target);
    var left = pane.attr("startLeft");
    var top = pane.attr("startTop");
    pane.css("position", "fixed");
    pane.css("top", top);
    pane.css("left", left);
}});
$("#test").draggable({create: function(e, ui) {
    var pane = $(e.target);
    var pos = pane.position();
    pane.attr("startLeft", pos.left + "px");
    pane.attr("startTop", pos.top + "px");
}, stop: function(e, ui) {
    var pane = $(e.target);
    pane.attr("startLeft", ui.position.left + "px");
    pane.attr("startTop", ui.position.top + "px");
}});

这将在html元素中存储顶部和左侧位置(需要xhtml文档类型才能有效),并使用该信息在调整大小事件结束时设置位置。


2

没有美感,但是在调整大小时如何将位置(top和left)保存在单独的变量中(我认为这个方法称为“开始”)?

更新(感谢评论...事件触发太晚了): 因为JqueryUI在创建可调整大小的对象时生成了第二个对象“ui”,所以它给该ui对象分配了一个字段:ui.originalPosition...那应该是调整大小之前固定元素的位置...


我运行了一个测试,看起来位置在开始事件触发之前就已经改变了。糟糕! - Chev
1
糟糕!我在窗口被拖动和/或创建的每个位置保存了位置。这使我在停止事件中获得了正确的位置,但你知道吗?它在停止事件之后改变了位置。真是让人发狂。 - Chev
很奇怪,我可以在“resize stop”事件中将位置更改为固定,但更改上方或左侧不起作用。这些必须在停止事件之后设置,没有其他解释。 - Chev
1
好吧,我撒了个谎,其实在停止事件中我可以设置位置。我只是错误地设置了CSS。真是傻!但是事实上,在开始事件中无法获取位置,因为它已经被改变了。 - Chev
只需在CSS中声明top/left为!important,它就会覆盖jQuery UI的操作。 - Mahn
显示剩余2条评论

1

这是一个不太好的解决方案,但对我有效。

this.resizable({
    start:function (event, ui){
         x =ui.originalPosition.left+ $(ui.originalElement).parent().scrollLeft()
         y = ui.originalPosition.top+ $(ui.originalElement).parent().scrollTop()
    },
    resize:function (event, ui){
         $(ui.originalElement).css('left' , x);
         $(ui.originalElement).css('top' , y);
}

0

我今天遇到了那个问题,我绝对不喜欢“不美观”的解决方案......所以我决定进行一些实验,看看是否有“更好”的解决方案......在某个时候,我有了一个直觉:

HTML:

<div class="fixed"></div>

JavaScript(jQuery):

$('.fixed').resizable();
$('.fixed').draggable();

CSS:

.fixed{
    position: fixed !important;
}

CSS 刚刚打败了 JQuery,太棒了!


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