0

I have an element with animated top margin. I need to detect if it isn't too close from the border, and if it is, scroll parent div to lower position, to prevent animated element from hiding. Here is an example:

http://jsfiddle.net/zYYBR/5/

This green box shouldn't be below the red line after clicking the "down" button.

ciembor
  • 7,189
  • 13
  • 59
  • 100
  • when you say scroll the parent, what element are you referring to in your example? – Zachary Kniebel Sep 10 '12 at 19:57
  • This element with scroll on the right (#container). – ciembor Sep 10 '12 at 20:03
  • Not sure what you are trying to do. Why even have a scrollable div? If you just want the green box to move down until it hits the red line and then stop, why not use position: relative and change the top style element, stopping when top + width >= the line's media box top? – Ed Bayiates Sep 10 '12 at 20:04
  • I have scrollable navigation with links and marker which is marking the active one. These links are refering to id's of sections in the content. Also when someone is scrolling content, the marker is moving to the link of currently visible section. When someone will scroll content to the end, marker will hide. So I want to scroll navigation with links when marker is at the bottom (let's say 40px up the bottom) of visible area. //edit I wan't to move green box each time when "down" is pressed. But move in relation to the inner, not container. – ciembor Sep 10 '12 at 20:11

2 Answers2

1

Do you mean this?

var new_margin;
var step = 75;
var limit = $("#max")[0].offsetTop;

$('#down').click(function() {
    var goStep = step;
    var elHeight = $("#animated")[0].offsetTop + $("#animated")[0].offsetHeight;    
    if((elHeight + step) > limit)
    {
        goStep = limit - elHeight;
    }
    new_margin = goStep +  parseInt($('#animated').css('margin-top'));
    $("#animated").animate({marginTop: new_margin}, 1000);   
});

http://jsfiddle.net/zYYBR/8/

EDIT: Or maybe something like that (of course you can improve the calculation, because currently it's very buggy with scroll):

var new_margin;
        var step = 75;
        $('#down').click(function () {
            scroll(1000);
        });

        var scrollTimer = null;
        $("#container").bind("scroll", function () {
            clearTimeout(scrollTimer);
            scrollTimer = setTimeout(function () { scroll(1); }, 10);
        });

        function scroll(speed) {
            var scrollStep, animationStep = step;
            var currentBoxBottom = $("#animated")[0].offsetTop + $("#animated")[0].offsetHeight;
            var nextCurrentBoxBottom = currentBoxBottom + step;
            var limit = $("#max")[0].offsetTop + $("#container")[0].scrollTop;
            if (nextCurrentBoxBottom > limit) {
                if (limit >= $("#container")[0].scrollTop) {
                    scrollStep = $("#container")[0].scrollTop + nextCurrentBoxBottom - limit;
                }
                else {
                    scrollStep = $("#container")[0].scrollTop - nextCurrentBoxBottom - limit;
                    animationStep = nextCurrentBoxBottom - limit;
                }

                $("#container")[0].scrollTop = scrollStep;
            }

            new_margin = animationStep + parseInt($('#animated').css('margin-top'));
            $("#animated").animate({ marginTop: new_margin }, speed);
        }

http://jsfiddle.net/zYYBR/13/

Alex Dn
  • 5,465
  • 7
  • 41
  • 79
  • Nope. Green box should go down (in relation to the #inner) each click the same distance down. But the #container should scroll down, when it is under the red line. – ciembor Sep 10 '12 at 20:20
0

Do you mean something like this?

I have the same visual result as Alex Dn did, but I added a little extra direction to what I think you're talking about. If it's what you're looking for I'll make updates:

var new_margin; var step = 75; var limit = $("#max")[0].offsetTop;

$('#down2').click(function() {
var anim = $("#animated");
var hrOff = $("#max").offset();
var thOff = anim.offset();
new_margin = Math.min(hrOff.top - thOff.top - anim.height(), 75);
console.log(new_margin, hrOff.top, thOff.top);
var st = 0;
if (new_margin < 75) {
    st = 75 - new_margin;
    //have container scroll by this much?
}

anim.animate({
    marginTop: "+=" + new_margin
}, 1000);
});​

http://jsfiddle.net/zYYBR/10/

Zachary Kniebel
  • 4,686
  • 3
  • 29
  • 53
  • Nope. Scroll still doesn't move (and box doesn't go down in relation to the #inner). – ciembor Sep 10 '12 at 20:25
  • @Alex Dn and ciembor I am so sorry - I accidentally posted Alex's code before as I was experimenting with it. I have updated my post with the correct code and the jsFiddle was the correct one from the start. Sorry again – Zachary Kniebel Sep 10 '12 at 20:26
  • @ciembor, I know that the window doesnt actually scroll - I just threw that comment in the code with a little draft to get my question across: is this what you're looking for, i.e. somehting like what I started to write that makes the container scroll by the extra amount? I can help you code it, but I don't want to waste time if that isn't what you're looking for – Zachary Kniebel Sep 10 '12 at 20:28
  • I think I already found solution: http://stackoverflow.com/questions/1397251/event-detect-when-css-property-changed-using-jquery . I should use it do detect margin-top change, and than scroll the container. – ciembor Sep 10 '12 at 20:30
  • I'm not going to pretend to know exactly what you're looking for, but I am pretty familiar with mutation observers and from what I understand from your question that is not what you want to do - it's a lot more work and you're going to need the same script anyway. but I could be wrong and I would never dissuade someone from trying a new technology. Let me know if you change your mind or need any further assistance. Good luck! :) – Zachary Kniebel Sep 10 '12 at 20:34
  • Here, this will be a good starting point for you if you want to learn about/implement mutation observers: http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#mutation-observers – Zachary Kniebel Sep 10 '12 at 20:36