Sign up ×
Stack Overflow is a community of 4.7 million programmers, just like you, helping each other. Join them; it only takes a minute:

I've been trying for days to figure this out. I have read many questions on SO as well as googled it many different ways and read/attempted everything I found. Nothing I have found so far has worked for me and I have rewritten my code a million times it seems trying out different methods for doing this.

I feel like there is some super obvious thing I am missing here, and maybe just need a push in the right direction. If I'm going about this completely wrong and need to restructure everything, I can do that too.

Any help is appreciated.

Basically what I am working with is a front end "controller" for lack of a better word, that initializes some variables, sets up some event listeners and responds to user actions.

I don't care if I use jQuery or pure Javascript, I just want it to work, even if I have to re-write the whole thing. My goal is speed and performance under heavy load. Another option I was considering was node.js but I have limited experience with that, so was hoping to figure it out with jQuery.

When the page loads, I do not get an error, but when I click one of the items that I have set an event listener on, I get the error... TypeError: Cannot Read Property 'apply' of undefined. And it refers to the corresponding line that starts with var scope = this ? function(e)...

The purpose of that line is to have the this keyword refer to the controller object so I can call object methods from within the event handler method. Though it seems it might not be working as I intended.

I tried to just use .on to set up the click and change handlers, but I was having problems with scope there as well. Any help, again, is much appreciated.

I will award a bounty to anyone who can help with this, even if you help before it is eligible I will send you a bounty once it becomes eligible so please don't hesitate to answer right away. I will pay the bounty as promised either way.

(function ($) {
    $(function () {  //document ready

        function Controller(authId, authKey) {

            this.user.id = authId;
            this.user.key = authKey;

            this.init();
        };


        Controller.prototype = {

            eventChange: [ "amt", "multi" ],
            eventClick: [ "double", "half", "high", "low" ],

            event: { refresh: ['amt', 'multi'], update: ['double', 'half'], process: ['high', 'low'] },

            user: { id: '', key: '', name: '', balance: '' },

            init: function () {

                this.initEvents();
           },
            initEventz: function() {

                for (var i = 0; i < this.eventChange.length; i += 1) {

                    var ele = document.getElementById(this.eventChange[i]);

                    var scope = this ? function(e) { this.handleEvent.apply(this, ["change"]); } : this.handleEvent;

                    if(document.addEventListener) {
                        ele.addEventListener("change", scope, false);
                    } else if(document.attachEvent) {
                        ele.attachEvent("onchange",  scope);
                    }
                }

                for (var i = 0; i < this.eventClick.length; i += 1) {

                    var ele = document.getElementById(this.eventClick[i]);

                    var scope = this ? function(e) { this.handleEvent.apply(this, ["click"]); } : this.handleEvent;

                    if(document.addEventListener) {
                        ele.addEventListener("click", scope, false);
                    } else if(document.attachEvent) {
                        ele.attachEvent("onclick",  scope);
                    }  
                }
           },
           handleEvent: function (e) {

              var eventId = e.target.id;

              for (var event in this) {
                    if (this.hasOwnProperty(event)) {

                           console.log(event);
                    }
              }
          }
        };
       var Controller = new Controller($("#auth").val(), $("#key").val());


    }); //end document ready

})(jQuery);
share|improve this question
up vote 1 down vote accepted

You are losing the reference to this.

You can solve that with this code:

var scope = this ? function(e) { this.handleEvent.apply(this, ["click"]); }.bind(this) : this.handleEvent;

but if you want that the handler have access to the element within his scope with the reference of this you should write this:

var scope = this ? function(e) { this.handleEvent.apply(ele, ["click"]); }.bind(this) : this.handleEvent;

or this

var that = this;

var scope = this ? function(e) { that.handleEvent.apply(ele, ["click"]); } : this.handleEvent;

I have seen other mistake. Because if this is undefined then scope is going to be this.handleEvent but this is going to raise an error because undefined can't have the handleEvent property.

share|improve this answer
    
OK, I used your first solution, by using bind(this), but now when it gets to the handleEvent method, I get the error that property 'id' is undefined when trying to access e.target.id. Any ideas? – Notorious Pet0 15 hours ago
    
Can I see your code running on codepen or somewhere ? I'm trying fix it but without the example is more difficult. I going to keep working on it :). I'm making changes on my answer. – gabrielperales 15 hours ago
    
Yes, the thing is that when you use apply, the first argument is going to be "the context", and the second argument is an array of arguments that you want to pass to the function, and you are passing "click" as the argument of handleEvent, and you are trying to read the property target.id of the string "click" – gabrielperales 15 hours ago
    
    
try this var scope = this ? function(e) { this.handleEvent.call(this, e); }.bind(this) : this.handleEvent; – gabrielperales 15 hours ago

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.