9

I have site where I want 'sub navigation'. So when you scroll to section, its tool bar will affix below the main toolbar. I have this working, but I can't change the top offset after initailization. The docs say:

affix('refresh')

When using affix in conjunction with adding or removing of elements from the DOM, you'll want to call the refresh method:

but when I try this I get:

Uncaught TypeError: Object # has no method 'refresh'

Here is my code:

$(function () {
    $('.sec-nav').addClass("affix-top");
    var adjustNavs = function (first) {
        $('.sec-nav').each(function (){
            var $p = $(this).closest('.sec');
            var $$ = $p.prevAll('.sec');
            console.log($$);
            var h = 0;
            $$.each(function () { h+=$(this).outerHeight();});
            console.log(h);

            if (first) {
                $(this).affix({offset: {top: h}});
            } else {
                $(this).data('affix', {b: {options: {offset:{top: h}}}});
                console.log(this);
                $(this).affix('refresh')
            }

        });
    }
    adjustNavs(true);
    $('.sec').bind('DOMSubtreeModified', function () {
        adjustNavs();
    });
});

I've tried different variation of

                $(this).data('affix', {b: {options: {offset:{top: h}}}});

including:

                $(this).affix({offset: {top: h}});

I cannot get the offset to change. How do you change the offset of the affix plugin? Thanks.

Fatmuemoo
  • 2,119
  • 3
  • 17
  • 34
  • 1
    Can you paste a block of the HTML? Quite difficult to tell otherwise... If you try replacing `$('.sec-nav').addClass("affix-top");` with `$('.sec-nav').affix();` does that help at all? Or have you already got the `data-spy="affix"` attribute on `.sec-nav`? – christian.thomas Aug 29 '12 at 15:36

3 Answers3

20

I figured it out. Instead of dynamically updating the offset, I changed the offset value to a function:

$(function () {
    $('.sec-nav').addClass("affix-top").each(function (){
        var $self = $(this);
        var offsetFn = function () {
            var $p = $self.closest('.sec');
            var $$ = $p.prevAll('.sec');
            var h = 0;
            $$.each(function () { h+=$(this).outerHeight();});
            return h;
        }
        $self.affix({offset: {top: offsetFn}});
    });
});

Now when a section changes due to dom manipulation or window re-size, the offset is automaticly changed due to the functions return value changing.

Fatmuemoo
  • 2,119
  • 3
  • 17
  • 34
  • 2
    Can you provide the html used, or a working example? I am trying to work this into my existing code, but I don't know what .sec is. – davecave Jun 06 '13 at 18:17
  • 1
    trying on window resize `$('.myMeny').affix({offset: {top: myOffet}});` but not working, the value didn't chage – sreginogemoh Dec 24 '13 at 23:29
  • Beautiful solution. Just works (by some voodoo I don't understand)... @davecave, to adapt the solution delete everything in offsetFn except for 'var h =' and 'return h;'. Then use your own elements and calculations to determine what the value of 'h' should be. – Just Plain High Aug 26 '14 at 11:37
  • Work like a charm! I tried with the window.resize, and don't worked. Thankfully I found this answer. – BernieSF Oct 16 '14 at 21:01
2

I simplified Fatmuemoo's answer slightly for a more basic case: My home page's nav bar (the default bootstrap #masthead) sits below a big background slider with id #bg. The height of the slider varies with 3 css breakpoints. We just set the offset of the #masthead to equal the height of the slider. Easy!

    $('header#masthead').affix({ //sticky header at bottom of bg
        offset: {
          top: function(){return $("#bg").outerHeight();}
        }
    });
Chris Chalmers
  • 494
  • 4
  • 13
  • Thanks, simple and efficient, works great and is easy to create a sum of all the elements you need. – EPurpl3 Nov 13 '15 at 15:15
0

how about:

            $(window).off('.affix');
            $("#ID_NAME")
                .removeClass("affix affix-top affix-bottom")
                .removeData("bs.affix");
            $('#ID_NAME').affix({ 
              offset: {
                top: OTHER_VALUE
              }
            });
Bla Bla
  • 49
  • 1
  • 9
  • Generally, answers are much more helpful if they include an explanation of what the code is intended to do, and why that solves the problem without introducing others. – Tim Diekmann May 27 '18 at 15:41