JQuery UI resizable does not support position: fixed; Any recommendations?
Asked Answered
A

7

14

JQuery UI's .resizable function does not support position: fixed; elements. The moment you try to resize them it switches their position attribute to absolute. Any recommended fixes?

I have some chat windows that pop up and are draggable around the document. They are position fixed so that they don't scroll with the page behind them. They all work perfectly until you try to resize a window, that's when it transitions to position: absolute; and then gets left behind when the page scrolls.

I tried handling the resize stop event and changing the position to fixed:

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

This doesn't work because the positioning (top: and left:) are not correct for the fixed element and when you stop resizing the element switches to fixed positioning and jumps to weird places on the page. Sometimes jumps out of the page boundries and is lost forever.

Any suggestions?

Algorism answered 27/1, 2011 at 17:9 Comment(2)
What about (and I haven't tested this) just putting it inside a container that's fixed?Detroit
What about just putting it inside a container that's fixed at 0 0?Detroit
P
11

To get over this problem I wrapped the .resizable() block with the .draggable() block:

<div id="draggable-dealie">
    <div id="resizable-dealie">
    </div>
</div>

the corresponding js:

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

and ensure you have the property position:fixed !important; set in the #draggable-dealie CSS:

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

I have a demonstration at: http://jsfiddle.net/smokinjoe/FfRRW/8/

Principally answered 20/2, 2013 at 0:50 Comment(3)
Bravo! This is a much better solution. JQuery UI just needs to fix this so you can use both on a single fixed element, but until then this is about as elegant a solution as I've seen.Algorism
The !important part fixed the problem for me and saved me lots of work. Thank you.Wrecker
Hardcoding top/left with !important solved the problems for me. It ain't pretty, but I'll take it, because it's either that or reimplementing the resizable logic by yourself.Dashpot
L
6

If, like me, you have a fixed div at the bottom of the page, then you can just add !important to these css rules to make it stick at the bottom :

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

And just make it resizable by its north border :

$('.fixed').resizable({
  handles: "n"
});
Laevorotation answered 5/2, 2013 at 22:3 Comment(1)
This should be the accepted answer for being css only, as opposed to html and js overhead.Overbold
M
3

Simply force position:fixed on the element when resizing starts and when resizing stops.

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

JSFiddle: http://jsfiddle.net/5feKU/

Moonlight answered 13/4, 2014 at 8:18 Comment(0)
P
2

No beauty but how about saving the position (top and left) in separate vars on the start of the resize (I think the method is called "start")?

UPDATE (Thank you for the comment... The event fires too late): As JqueryUI generates a second object "ui" on making a object resizable it gives that ui-object a field: ui.originalPosition... That should be the position of the fixed element before the resizing...

Proletariat answered 27/1, 2011 at 17:14 Comment(7)
I don't know why I didn't think to try that. Cross your fingers :)Algorism
I ran a test, it looks like that position is changed BEFORE the start event fires. Dang!Algorism
GAH! So I saved the position in every place where the window gets dragged and/or created. That gets me the correct position in the stop event, but guess what? IT CHANGES THE POSITION AFTER THE STOP EVENT. RAGE.Algorism
It's so weird that I can change the position to fixed in the resize stop event, but changing top or left does nothing. Those have to be getting set after the stop event, there is no other explanation.Algorism
Okay so I lied, I can set the position on the stop event. I was just setting the CSS incorrectly. D'OH! But it is true that you can't get position in the start event as it's already been changed.Algorism
UPDATE: In IE it would jump while resizing (disappear) and then appear back when done resizing. Instead of the resize stop event, I had to use the resize "resize" event so it constantly updates the position while resizing. That fixes IE.Algorism
Just declare top/left as !important in your css and it will override what jquery ui is doing.Dashpot
N
2

Here's the solution I came up with, it's a little more code than I'd like, but it fixes the problem:

$("#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");
}});

This stores the top and left position in the html element (needs xhtml doctype to be valid) and uses that information to set the position at the end of the resizing event.

Nealneala answered 4/2, 2011 at 20:46 Comment(0)
T
1

This is a dirty solution but works for me.

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);
}
Trabzon answered 7/2, 2013 at 17:14 Comment(0)
C
0

I had that problem today, and I absolutely hate "un-aesthetic" workarounds... So I decided to experiment a little to see if there wasn't a "better" solution ...and at some point I had a hunch:

html:

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

javascript (jquery):

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

css:

.fixed{
    position: fixed !important;
}

Jquery just got outplayed by CSS, damn!

Commodore answered 15/5, 2012 at 13:34 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.