2

I want to be able to drag a divider up and down to resize the divs above and below the divider on a fixed page height. These divs could be in a table, although they need not be.

In short, I would like to be able to emulate what happens on the jsFiddle site, although I only need the vertical resize. jsFiddle have used mooTools, but I want to do it with jQuery.

One important complication: I won't know the size of the div above the divider until it is actually built dynamically, so I can't just start with a set absolute positioning.

What is the best way forward? I have a feeling I'll just be reinventing the wheel if I don't ask :)

[BTW: a couple of questions with similar names are linked to jsFiddle examples that don't work (for example, this).

So far I have used this:

    $('.rsh').draggable({
        axis:'y',
        drag: function (event, ui) {            
            var offsettop = ui.offset.top;
            $(this).prev().css({
                height: offsettop
            });
    });

Needless to say, it ain't workin' right yet.

Community
  • 1
  • 1
Nick
  • 5,995
  • 12
  • 54
  • 78
  • If plugins will do you can try this: http://jqueryui.com/demos/resizable/ – Playmaker Jun 16 '12 at 09:10
  • Yes, I looked at this, @Playmaker, although I'm not sure how to make it work. Draggable seemed a better option. – Nick Jun 16 '12 at 09:12
  • Draggable is for drag and drop, and you want resize if i am right. – Playmaker Jun 16 '12 at 09:14
  • for resizable, you just have to add this script, ' $(function() {$( ".classname" ).resizable();}); '​ which will make all elements with class 'classname' resizable – Playmaker Jun 16 '12 at 09:19
  • 1
    Yes, you can easily make elements resizable. The question is, however, how to get the handler (which is a different div) to drive the resizing of the other elements. You'll note that on the jsFiddle site, the DOM element you drag is not the one that is being resized. – Nick Jun 16 '12 at 09:22
  • I got it to work nicely with this: `$('.rsh').draggable({ axis: 'y', helper: 'clone', drag: function (event, ui) { var height = ui.offset.top - 85; $(this).prev().height(height); } });` I think I'll delete the post, though :) – Nick Jun 16 '12 at 09:33
  • Rather add it as an answer and accept it.. for future posters. – Playmaker Jun 16 '12 at 09:36

3 Answers3

6

In case anyone is interested in the future, I got it to work nicely with this:

$('.rsh').draggable({
    axis: 'y', 
    containment: 'parent',
    helper: 'clone', 
    drag: function (event, ui) { 
        var height = ui.offset.top - 85; 
        $(this).prev().height(height); 
    } 
});

This is the fiddle.

The use of clone is the key. The draggable elements (.rsh) are relative, so if you don't use a clone the element moves twice as far as the mouse because it is also affected by the change in the height of the previous div.

Note: The - 85 is just a quirk of the page layout making allowance for the header and so forth.

Nick
  • 5,995
  • 12
  • 54
  • 78
2

This is a version of Nick's code (which was really helpful, thanks!) that allows subsequent dividers to remain static. It works by resizing the divs above and below the dragged divider in opposite directions.

$('.rsh').draggable({
    axis: 'y'
    ,containment: 'parent'
    ,helper: 'clone'
    , start: function(event, ui) { 
        $(this).attr('start_offset',$(this).offset().top);
        $(this).attr('start_next_height',$(this).next().height());
    }
    ,drag: function (event, ui) {           
        var prev_element=$(this).prev();
        var next_element=$(this).next();
        var y_difference=$(this).attr('start_offset')-ui.offset.top;            
        prev_element.height(ui.offset.top-prev_element.offset().top);
        next_element.height(parseInt($(this).attr('start_next_height'))+y_difference);
    } 
});
Flam
  • 106
  • 5
1

Here is another alternative to Nick's version, it automatically moves the horizontal handler to the top and to zero as a nice effect. Also, it adjusts the height size of both sections mutually.

$('.horizontal_handler').draggable({

        axis: 'y', 
        containment: 'parent',
        helper: 'clone', 
        drag: function (event, ui) { 

            var height = ui.offset.top - 220 // 220 : initial top margin to the previousDiv
            , referenceHeight = nextDivHeight + previousDivHeight  //500 px initial height size
            , previousSection = $(this).prev()
            , nextSection = $(this).next();

            if ((nextSection.height() === 0) && (referenceHeight - height < 0)){
                return;
            }

            previousSection.height(height); 
            nextSection.height(referenceHeight - height ) ;


            if (nextSection.height()< 20){
                    previousSection.height( height+ nextSection.height() );
                    nextSection.height(0);
                }

            if (previousSection.height()< 20){
                    nextSection.height(referenceHeight - height - previousSection.height() );
                    previousSection.height(0); 
                }
        } 
    });
Alberto Montellano
  • 5,886
  • 7
  • 37
  • 53