Der Kev
Der Kev

Reputation: 69

uncaught TypeError: Cannot read property "top" of null

I got a pretty annoying javascript error. The world famous:

uncaught TypeError: Cannot read property "top" of null

Here is the code:

$(function() {

var setTitle = function(title, href) {
        title = 'Derp: ' + title;
        href = href || '';

        history.pushState({id: href}, title, href.replace('#', '/'));
        document.title = title;
    },
    scroll = function(url, speed) {

        var href = typeof url == 'string' ? url : $(this).attr('href'),
            target = $(href),
            offset = target.offset(),
            title = target.find('h1').text();

        if(typeof url == 'number') {
            target = [{id:''}];
            offset = {top: url};
        }

        //  And move the element
        if(offset.top) {
            //  Set the new URL and title
            setTitle(title, href);

            //  Make sure we're not moving the contact panel
            if(target[0].id != 'contact') {
                $('html, body').animate({scrollTop: offset.top}, speed);
            }
        }

        return false;
    };

//  Handle existing URL fragments on load
if(location.pathname.length > 1) {
    scroll(location.pathname.replace('/', '#'), 0);
}

$('a#logo').click(function() {
    $('html,body').animate({scrollTop: 0});
    return false;
});

//  Handle internal link clicks
$('a[href^=#]:not(#logo)').click(scroll);


//  Close the "Get In Touch" box
var box = $('#contact'),
    moveBox = function() {
        var closing = $(this).attr('class') == 'close',
            amount = closing ? -(box.height() + 20) : 0,
            cb = closing ? '' : function() { box.animate({marginTop: -10}, 150); };

        box.animate({marginTop: amount}, cb);
    };

box.css('margin-top', -(box.height() + 20));
$('#contact a.close, #get-in-touch').click(moveBox);


//  Nasty little fix for vertical centering
$('.vertical').each(function() {
    $(this).css('margin-top', -($(this).height() / 2));
});


//  Work panels
var parent = $('#work'),
    panels = parent.children('div');

panels.each(function() {
    $(this).css('width', 100 / panels.length + '%');
})

parent.css('width', (panels.length * 100) + '%');


//  Bind the keyboards
$(document).keyup(function(e) {
    var actions = {
        //  Left
        37: function() {
            var prev = panels.filter('.active').prev().not('small');

            if(prev.length > 0) {
                prev.siblings().removeClass('active');

                setTitle(prev.find('h1').text(), prev[0].id);

                setTimeout(function() {
                    prev.addClass('active');
                }, 250);

                parent.animate({left: '+=100%'}).css('background-color', '#' + prev.attr('data-background'));
            }
        },

        //  Right
        39: function() {
            var next = panels.filter('.active').next();

            if(next.length > 0) {
                next.siblings().removeClass('active');

                setTitle(next.find('h1').text(), next[0].id);

                setTimeout(function() {
                    next.addClass('active');
                }, 250);

                parent.animate({left: '-=100%'}).css('background-color', '#' + next.attr('data-background'));
            }
        },

        //  Down
        40: function() {
            var w = $(window),
                height = w.height() * panels.children('div').length,
                h = w.height() + w.scrollTop();

            if(h < height) {
                scroll(h);
            }
        },

        //  Up
        38: function() {
            var w = $(window);
            $('html,body').animate({scrollTop: w.scrollTop() - w.height()});
        }
    };

    //  Call a function based on keycode
    if(actions[e.which]) {
        actions[e.which]();
    }

    e.preventDefault();
    return false;
});


//  Fix crazy resize bugs
$(window).resize(function() {

    var m = $(this),
        h = m.height(),
        s = m.scrollTop();

    if((h - s) < (h / 2)) {
        m.scrollTop(h);
    }

    //$('html,body').animate({scrollTop: s});
});


//  slideshow
var woof = function() {
        var slides = $('#molly li'),
            active = slides.filter('.active');

        if(!active.length) {
            active = slides.last();
        }

        active.addClass('active');

        var next = active.next().length ? active.next() : slides.first();

        next.css('opacity', 0).addClass('active').animate({opacity: 1}, function() {
            active.removeClass('active last-active');
        });
    };

setInterval(woof, 3000);


//  easing
$.easing.swing = function(v,i,s,u,a,l) {
    if((i /= a / 2) < 1) {
        return u / 2 * (Math.pow(i, 3)) + s;
    }

    return u / 2 * ((i -= 2) * i * i + 2) + s;
};

//  Change the default .animate() time: http://forr.st/~PG0
$.fx.speeds._default = 600;
});

try{Typekit.load()}catch(e){}

Sorry for this long monster but I thought it could be useful for you to see the whole thing. The Error warning shows up in this part:

//  And move the element
        if(offset.top) {

Uncaught TypeError: Cannot read property 'top' of null

It's line 23 in the code.

That's it. Could you give me a hint on how to solve this problem? Thank you!

Upvotes: 6

Views: 16313

Answers (2)

user1233508
user1233508

Reputation:

According to jQuery source, jQuery.fn.offset only returns null if:

  1. the first element in the set doesn't exist (empty set) or
  2. its ownerDocument is falsy (I don't know when that would happen, sorry).

The first option seems more likely, so you should check if target.length > 0 before calling target.offset() and handle the alternative.

Upvotes: 0

S.831
S.831

Reputation: 123

var href = typeof url == 'string' ? url : $(this).attr('href'),
target = $(href), //line 2
offset = target.offset(), //line 3

I believe this must have something to do with line 2, target should be null when error occurs

Upvotes: 2

Related Questions