TeamSpace
Quality vs. quantity Microphone
Home Who We Are What We Do What We've Done Why Work For Us Blog Contact Us

Using jQuery resizable and draggable with fixed position pop up

Monica Mora - October 22 2013 01:45:00 PM


For our purposes, we needed a pop-up that would stay in the viewable section of a web page and allowed the user to move and resize it using jQuery.

Now at this point, most of you are thinking, just use a jQuery dialog right? That's what I thought too! Draggable and resizable are built in....don't reinvent the wheel, use what's there right? So, I build the pop-ups using dialogues, and set obj.draggable () and obj.resizable(). Simple right? One would think so....

Under "normal" conditions this would be the case, set the two properties and move on to the next set of code.

So I set the dialogue to draggable, and life is good. The user can move the dialogue all over the viewable section of the page and all is not lost if the user scrolls.

Now, I add resizable property and test resizing the dialog on initial load of the page, and it works  beautifully.

I move on to the next scrollable section to test another dialog call and here's where it breaks. The dialog loads fine, drags fine, but upon resize, the dialog disappears. Wonderful. I look at the calls, compare the dialog functions verify everything is using the correct calls, etc.

After many hours of combing through function calls, checking firebug for errors, console log statements and yes, even alerts, I've come to the conclusion that there are no errors and no differences in code.

I move to the top of the page, it works. I scroll the page, it disappears.  So at this point, I do what all good developers do, I use a different function. If the jQuery dialog won't conform to my needs, I'll write my own pop-up!

So, here we go, rewriting every "dialog" call...using a fixed position div and visibility. Of course, I test the new pop-up with simple styles and no resizable or draggable properties. Everything works similarly to the dialog. Great!

Now, I think, let's add the draggable, and viola....perfect!

Last test. At this point, I'm confident all will work as I want it to. I'm feeling maybe a touch superior,  I've bent this code to my will! I am the developer king! I can do anything!

Then, I add the draggable and what do you think happens? Of course, same behavior as the dialog. Are you kidding me?? Seriously!!!???

At this point, I do what all good developers do and  I refrain from throwing my computer out the window and walk away. I clean the house, do some laundry, cook dinner and stew over the fact that this code SHOULD work.

I'm thinking what could be breaking it. What on earth could "resizable" be doing that is so finicky??

Then it hits me. BAM. I go back to the computer and check my theory.

I scroll to the middle of the page, activate the pop-up, drag it and then resize it. At this point, I scroll BACK TO THE TOP of the page, and what to my wondering eyes appear? There it is, my resized pop-up sitting at the top of the page.

Of course!  Nothing I do ever fits the mold of "normal".  In this case, we have a long scrolling page with distinct "sections" the user can navigate to via a set of navigation buttons. This being the case, the pop-ups needed to be set to a "fixed" position, thus keeping the pop up in view should the user decide to scroll the page behind it.

jQuery resizable is smart enough to reset the position of my pop-up for me. Why thank you jQuery, your so kind...and NOT cool!

Yes, what happened was my beautifully styled, FIXED position div has been hijacked!!! jQuery has now set my position to absolute with exact left/top positions.

Curse you jQuery! And your little dog too!!!

The obvious solution here, or so it seems, is to simply add a "!important" to the fixed position css style definition.  Typically, "!important" would , in fact, solve this issue, given that the top and left definitions were non-changing and the page wasn't long enough to scroll. While this provided partial relief, my needs were a little more complicated than that of a "normal" page, and this lone solution left me with a "jumpy", erratic and unpredictable behavior, not the smooth resize one might expect.

After a few more hours, I decide to set the position to fixed, and  set the top and left position in the javascript.  This seems like a simple solution that would come to any developer and again, I'm confident.

Upon testing, not so much. Again, hacked by jQuery! Curses! How can I get my calls to sit "below" their calls...and not make the pop-up look "jumpy"....????

Now, I've resorted to google...and it seems I'm not alone. I'm not the only person that has ever needed to set a fixed position pop-up to be resizable.

In combing through many posts...the answers are redundant. They all say "jQuery resizable does not support fixed positioning". WHAAAAAAAT??? Seriously???

In the end, I found a few solutions posted that suggest resetting the position to fixed post resizing. Well I've already tried this.

It finally hits me. I need to set the position to fixed DURING the event, not after! Viola...Success, I feel like Julie Andrews in "The Sound Of Music"! It works. It doesn't jump. It doesn't "move". It does exactly what I want it to do!

So now, for those of you that are less "visual" than I, here is the actual code solution:

First, 2 functions that will resize my iFrame and container:

function resizeURLBox(){
  //size outer box to window
  var uBox=$('#urlBox')
  var divWidth = Math.min($(window).width() - 25, 1000);
  uBox.height(($(window).height() - 130) + 'px');
  uBox.width(divWidth + 'px')
}

function resizeURLFrame(){
  //size inner frame to outer box
  var uFrame = $('#urlFrame');
  uFrame.height(($('#urlBox').height() - 28) + 'px');
  uFrame.width($('#urlBox').width()-2 + 'px');
}


Then, during the pop-up call, in the 'draggable' parameters I added the fixed position to the start event:  

var uBox=$('#urlBox')
  uBox.draggable({handle:'#urlDrag', scroll: false});
  uBox.resizable({
          handles: 'n,s,e,w,ne,se,nw,sw',
          start: function(e, ui) {
          uBox.css('position', 'fixed')
          uBox.css('top', (60)+'px');
          $(window).off('resize', resizeURLBox);  //cancel window resize event s
          $(window).off('resize', resizeURLFrame);
          var d = $("<div class='iframeCover' style='zindex:99;position:absolute;width:100%;top:0px;left:0px; height:" + $('#urlBox').height() + 'px'></div>');
          $('#urlBox').append(d);
  },
          resize: function(e, ui) {
          resizeURLFrame()  // resize the inner iFrame as the container is resized
  },
          stop: function(e, ui) {
                  $(window).resize(resizeURLBox); //add window resize events back
                  $(window).resize(resizeURLFrame);
                  $('.iframeCover').remove();
          }
  });        


VIOLA! I now have a pop-up that will bend to my will, and even resize itself on browser resize. It does it all!