Search code examples
javascriptjqueryextend

jQuery extend, cannot read property of undefined


I have this code:

var viewport = $(window),
    viewport_height = viewport.height();

var _topPanel = jQuery.extend({
    el: $('.js-lp_top'),
    //
    height: function() {
        var self = this;

        self.el.css('min-height', viewport_height);
    },
    scroll : function() {
        var self = this;
        var scrolled = viewport.scrollTop();

        viewport.on('scroll', function() {
            self.el.css({
                'top': (49 - (scrolled / viewport_height) * 80) + '%'
            });
        });
    }
});
var topPanel = new _topPanel.height().scroll();

And an jQuery error that Cannot read property 'css' of undefined. What i'm doing wrong? Thx for help.


Solution

  • Let's first examine this line of code.

     var topPanel = new _topPanel.height().scroll();
    

    The keyword new creates a new empty object. Inside the height function, the this keyword refers to this new object, which of course doesn't have an el property. self.el is undefined, hence the error message Cannot read property 'css' of undefined

    There are two changes to make here:

    1. Ensure your height and scroll functions returns this, to support function chaining

    2. Don't include the new keyword when invoking the height function

    Here's the modified code:

    var _topPanel = jQuery.extend({
        el: $('.js-lp_top'),
        //
        height: function () {
            var self = this;
    
            self.el.css('min-height', viewport_height);
            return self;
        },
        scroll: function () {
            var self = this;
            var scrolled = viewport.scrollTop();
    
            viewport.on('scroll', function () {
                self.el.css({
                    'top': (49 - (scrolled / viewport_height) * 80) + '%'
                });
            });
            return self;
        }
    });
    var topPanel = _topPanel.height().scroll();