ScrollToFixed icon indicating copy to clipboard operation
ScrollToFixed copied to clipboard

Update initial position of bottom and top 'sticky div', when content dynamically changes height

Open Felix-MFU opened this issue 11 years ago • 19 comments

Hello, first of all thank you for your great plugin!

My Problem:

I created a one-pager with a sidebar navigation which includes the two types scrollToFixed elements: 'maginTop' and 'bottom'. Basically there are always two elements for one link, one that sticks at the top when scrolling down and a copy of it that sticks at the bottom of the page when scrolling up. All this works fine.

What doesn't work is to dynamically update the height when some element changes its height. In my case a slider (Flexslider) does that. The scrollToFixed Plugin remembers the initial position of each sticky element, but doesn't update their values when the position changes.

Please take a look here:

http://jsfiddle.net/LhNr4/22/

Each Menu-Item (apart from 'welcome') should be aligned with the corresponding title, once scrolled to their position. 'Item 4' has a wrong value from the very beginning (it should align with the Title 'Item 4') and doesn't update once the slider-div changes its height.

I have tried the suggested method to trigger $(window).resize(); via a FlexSlider Callback, when a slider operation is finished to make scrollToFixed recalculate its values, but that doesn't seem to work.

// Callback API start: function () { $(window).resize(); }, after: function () { $(window).resize(); },

This is my scrollToFixed function, which seems to work otherwise:

var menuitems = $('.menuitem');

function registerNav() {

menuitems.each(function (i) {
    var menuitem = $(menuitems[i]);
    var next = menuitems[i + 1];
    var prev = menuitems[i - 1];
    var theIndex = $(this).prop('title');
    var theItem = $(this).attr('id');
    // counts all menu items
    var numItems = $('div.menuitem_top').length;
    var elements = $('.menuitem_top');
    var reversedIndex = (elements.length - elements.index(this));



    $(this).scrollToFixed({
        marginTop: $(this).outerHeight(true) * theIndex,
        zIndex: 1999,

        fixed: function () {
            $('.menuitem_bottom_' + theIndex).addClass("hide");
            $(this).addClass("active");
            $(prev).addClass("inactive");
        },

        postFixed: function () {
            $('.menuitem_bottom_' + theIndex).removeClass("hide");
            $(this).removeClass("active");
            $(prev).removeClass("inactive");
            $(prev).addClass("active");
        },

    });

    $('.menuitem_bottom_' + theIndex).scrollToFixed({
        bottom: $(this).outerHeight(true) * reversedIndex,
        limit: $('.menuitem_bottom_' + theIndex).offset().top,
        zIndex: 2999,
        fixed: function () {
            $('.menuitem_top_' + theIndex).addClass("hide");
            $('.menuitem_top_' + theIndex).addClass("hide");
        },
        postFixed: function () {
            $('.menuitem_top_' + theIndex).removeClass("hide");
        },

    });

});

I hope you can help me with this.

Felix-MFU avatar Dec 11 '13 14:12 Felix-MFU

Very cool! I like what you are trying to accomplish.

The marginTop and limit properties can also be functions. This will recalculate positions every time they are called instead of remembering the original positions. This works well for dynamic pages where elements change size or show/hide.

Try wrapping those in function blocks.

Good luck!

bigspotteddog avatar Dec 11 '13 15:12 bigspotteddog

Thank you! I want to make the code publicly available use once this is accomplished.

I tried what you suggested once before, with no luck. "bottom: …" seems to entirely ignore functions. And "limit: …" as well as "marginTop: …" give really strange results. I'm quite new to javascript, maybe I'm doing it wrong.

Here's what I did:

The top element: marginTop: function () { return $(this).outerHeight(true) * theIndex ; }

The bottom element: limit: function () { return $('.menuitem_bottom_' + theIndex).offset().top ; }

And that's the funny / bad result: http://jsfiddle.net/FelixDampf/LhNr4/24/

Also I'm worrying about something else: When the height of the slider animates, the according Link (4) should do the same and move down with it instantly. Since the plugin overrides the position css (relative) to absolute, I don't see how this can be accomplished.

Any ideas?

Felix-MFU avatar Dec 11 '13 18:12 Felix-MFU

I will have a closer look later today.

bigspotteddog avatar Dec 12 '13 17:12 bigspotteddog

That is a pretty complex layout. I will have to look at this when I have more time.

A quick note, "this" probably won't work in a function block passed into scrollToFixed. You will have to set a variable outside of the block and use that instead as this often points to the wrong thing.

var self = this;
var thing = {
    f: function() {
        console.log(self == this); // this returns false
    }
};
thing.f();

bigspotteddog avatar Dec 13 '13 00:12 bigspotteddog

Thank you so much for taking your time.

I tried to implement your suggestion (the way I understood it), but it doesn't seem to change anything to the previous version.

http://jsfiddle.net/FelixDampf/LhNr4/25/

var menuitems = $('.menuitem');

    function registerNav() {

    menuitems.each(function (i) {
        var menuitem = $(menuitems[i]);
        var next = menuitems[i + 1];
        var prev = menuitems[i - 1];
        var theIndex = $(this).prop('title');
        var theItem = $(this).attr('id');
        // counts all menu items
        var numItems = $('div.menuitem_top').length;
        var elements = $('.menuitem_top');
        var reversedIndex = (elements.length - elements.index(this));

        var self = this;
        var thing = {
        f: function() {
            console.log(self == this); 
               // this returns false
                }
        };
        thing.f();



        $(self).scrollToFixed({
            marginTop: function () { return $(self).outerHeight(true) * theIndex ; }
            ,
            zIndex: 1999,

            fixed: function () {
                $('.menuitem_bottom_' + theIndex).addClass("hide");
                $(self).addClass("active");
                $(prev).addClass("inactive");
            },

            postFixed: function () {
                $('.menuitem_bottom_' + theIndex).removeClass("hide");
                $(self).removeClass("active");
                $(prev).removeClass("inactive");
                $(prev).addClass("active");
            },

        });

        $('.menuitem_bottom_' + theIndex).scrollToFixed({
            bottom: $(self).outerHeight(true) * reversedIndex,
            limit:  function () { return $('.menuitem_bottom_' + theIndex).offset().top ; },
            zIndex: 2999,
            fixed: function () {
                $('.menuitem_top_' + theIndex).addClass("hide");
                $('.menuitem_top_' + theIndex).addClass("hide");
            },
            postFixed: function () {
                $('.menuitem_top_' + theIndex).removeClass("hide");
            },

        });

    });




};

registerNav();

});

Felix-MFU avatar Dec 13 '13 14:12 Felix-MFU

Hi folks,

I have a similar problem. In my case is a header at the top with the login, account and so on. Below a summary is now fixed with MarginTop and the bottom is a footer with bottom: 0 In addition I have another plugin (a filter slider) that dynamically changes the height of the content. The navigation (summary1) works quite normal, but the footer limit does not change dynamically with the total height of the page. I tried to make everything into a function, but then the footer begins to flicker. Look at this: http://stackoverflow.com/questions/20516645/scrolltofixed-limit-issue-and-flickering

Yes, that is a really strange issue.

Also, I do not think it solves the problem to put the limit in a function in this case.

Please help me to figure this out. Thanks Michael

M1kn avatar Dec 20 '13 15:12 M1kn

@M1kn Create a marker element, I called mine .footer-marker, placed just above the .footer. Then, use this in the footer's limit function.

limit: function() { return $('.footer-marker').offset().top; }

Here is the modified fiddle:

http://jsfiddle.net/ZczEt/1650/

I removed the summary outer height subtraction as it did not appear to do anything.

Also, the summary now returns a function for its limit as I am assuming the summary has dynamic content. The limit as a function here will compensate for dynamic content loaded into the summary.

Hope that helps.

bigspotteddog avatar Dec 20 '13 16:12 bigspotteddog

@FelixDampf The window resize handler is failing due to registerNav() not being visible to it. I moved this into the document ready function so it can see it. That doesn't fix the issue, but it does make the window resize event call registerNav().

bigspotteddog avatar Dec 20 '13 16:12 bigspotteddog

@FelixDampf I am trying to simplify the layout for debugging as there is a lot of movement and it is difficult to see what is going on. I will have to come back to this again later.

bigspotteddog avatar Dec 20 '13 16:12 bigspotteddog

Thank you for your help. I tried to implement the marker element, with no luck. It does weird things. It seems to me the bottom element can't handle functions in general.

I did this on basis of the first sketch ( http://jsfiddle.net/LhNr4/22/ ), which was the only one that seemed to work more or less so far http://jsfiddle.net/LhNr4/29/

Felix-MFU avatar Dec 20 '13 17:12 Felix-MFU

@FelixDampf The marker comment was for @M1kn. He/she joined the thread this morning. I modified the comment to make that more clear.

bigspotteddog avatar Dec 20 '13 17:12 bigspotteddog

@bigspotteddog thank you very much for your great support. The bottom element is getting strange in every way I tried to use. I think it´s a offset issue. Hope thats helping us both out. Thanks

M1kn avatar Dec 21 '13 01:12 M1kn

@bigspotteddog Here is another fiddle to show you my problem: http://jsfiddle.net/zRZ2e/1/

The view more buttons point out what happens with my dynamic plugin.

M1kn avatar Dec 23 '13 10:12 M1kn

@M1kn Here is a fiddle update which moves the footer with the latest fiddle you provided. However, the summary will not move with a shorter content height because it is not yet docked. For that case, you might want to change the z-index so it goes under the footer.

http://jsfiddle.net/zRZ2e/2/

bigspotteddog avatar Dec 27 '13 15:12 bigspotteddog

@M1kn For this update, I simply removed the position: absolute style from the #summary. That makes the summary go under the footer for the short content case.

http://jsfiddle.net/zRZ2e/3/

bigspotteddog avatar Dec 27 '13 15:12 bigspotteddog

@bigspotteddog I know my sketch probably asks for too much of an investigation, but do you think there is a solution for my problem at all? I wonder if the plugin is capable of not just updating its values, but smoothly sliding its (mainly bottom) elements dynamically, according to a page's content.

Felix-MFU avatar Dec 28 '13 17:12 Felix-MFU

Hi @FelixDampf,

I think the plugin could be modified to better facilitate your use case. There are some challenges that are not easily addressed at this time. Could it be done? Yes, I think so. It will take some work to get there though.

As I maintain this plugin in my spare time, of which I do not have much, I have not been able to dig much deeper into this particular issue. I have created a local copy of the setup so I can debug and make modifications more easily than a fiddle. I have seen some markup issues that I would need to rearrange. I turned off the plugin and css to see where things fall, then turned things back on to see the interactions. I have not gotten much farther than that. I wish I had more time to help and I will continue to look at this as time comes available.

I wish you the best of luck and I will keep updating this ticket as I learn more.

Happy Holidays!

Sincerely, bigspotteddog

bigspotteddog avatar Dec 28 '13 19:12 bigspotteddog

Dear @bigspotteddog,

I very much appreciate the work you have done on this plugin and the amount time and effort you invest to solve problems of others like myself.

Thank you very much for your support. All the best to you and happy holidays!

Warm regards, Felix

Felix-MFU avatar Dec 31 '13 10:12 Felix-MFU

Thank you guys, this save me a monstrous headache :+1:

jacquesletesson avatar Oct 11 '14 20:10 jacquesletesson