jQuery .offset() returns undefined value

10,647

You are returning the same value in each iteration. the cached this object doesn't refer to your section collection's elements, it refers to the window object. Use $(this) instead of the obj in the map's callback.

Share:
10,647

Related videos on Youtube

Marian
Author by

Marian

I'm actually into permaculture and auto sustainability in rural areas. Still doing some coding here and there for fun and work but really looking into other things. Jade and SASS are awesome, try it! I'm a fan of ditching jQuery for vanilla JavaScript and am looking into ES6/7 and ReactJS right now.

Updated on June 04, 2022

Comments

  • Marian
    Marian almost 2 years

    I built this very basic .map() function with jQuery to store the top offsets of my HTML sections in an array (inside script tag at the very end of the body):

    jQuery

    $(window).load(function() {
        var obj = $(this),
            sec = $('section'),
            arr = sec.map(function() {
                      return obj.offset().top
                  }).get();
    })
    

    It's almost as simple as in the jQuery documentation. And it already worked! ... Until like a week ago.
    My HTML (jade [compiled with CodeKit]) has a very simple structure either:

    HTML

    body.preload
        section#id1
            whateverContent
        section#id2
            moreContent
        section#id3
            evenMoreContent
        ...
    

    Surprisingly today the console decided to tell me that top is undefined:

    Console

    Uncaught TypeError: Cannot read property 'top' of undefined
    

    Supposedly in my function .map() takes all section tags and returns the offset of each iterated element just as stated in the documentation:
    Within the callback function, this refers to the current DOM element for each iteration.
    Not even to mention again that this has already worked rock solid for me about a week ago.

    So what's the issue here?

    Is there a typo? Is something in between messing around? I got more variables defined there, but it shouldn't make any difference, should it? Could it have to do something with compiling jade? With CodeKit? Any clues are highly appreciated!

    This is my uncensored, complete JS on the page (worked a week ago):

    // Let DOM finish loading
    $(window).load(function() {
        // CSS animation hack
        $('body').removeClass('preload')
        // Sticky nav and active class
        var win = $(window),
            doc = $(document),
            obj = $(this),
            sec = $('section'),
            nav = $('nav'),
            anc = $('nav a'),
            pos = nav.offset().top,
            // Fill array with top offsets from sections
            arr = sec.map(function() {
                        return obj.offset().top
                  }).get(),
            act = function() {
                        win.scrollTop() > pos ? nav.addClass('sticky')
                        : nav.removeClass('sticky'),
                        $.each(arr, function(i, val) {
                                (win.scrollTop() > val && win.scrollTop() < (val + sec.eq(i).outerHeight(true) + 1) ) ? anc.eq(i).addClass('active')
                                : anc.eq(i).removeClass('active')
                        })
                    };
        // Execute sticky function
        win.scroll(act)
    
    • Ram
      Ram over 9 years
      You are returning the same value in each iteration. the cached this object doesn't refer to your section elements, it refers to the window object. Use $(this) instead of the obj in the maps callback.