0

Seeking to create an event handler that registers a callback and iterates based on the event.

An early, working example is something like this:

var elt = document.getElementById("square"),
      clickCount = 0;

  // call a priviledged method with access to prviate vars from 
  // outer scope
  var count = function () {
    clickCount += 1;
    alert("you clicked me " + clickCount + " times!");
  };

  elt.addEventListener("click", count, false);

Now I want to actually write something js I could use. Here is the current construction:

//Create a class object
function CountMe () {

 //privately scoped variables
  var clickCount = 0;

 //methods on 'class' CountMe
  this.countClick = function () {
    //who's context am I in?
    this.addCount();
    alert("you clicked me " + clickCount + " times!");
  };

  this.addCount = function() {
    clickCount += 1 
  };
};

// Create an instance of countMe class
var clickMe = new CountMe();

//Add an event listener for clicks 
document.getElementById("square").addEventListener("click", clickMe.countClick ,false)

The error I receive is Uncaught TypeError: Object #<CountMe> has no method 'addEventListener' Given an html page like this:

<html>
<body>
 <div style="width:50px; height:50px; background-color:red;" id="square">
 </div>
</body>
</html>

My questions are:

  • How should this be constructed so onclick events function as they do in the first method?
  • In the method countClick what context is the nested this in? The instance of the CountMe class I suspect, just want someone else's take.
rhodee
  • 1,257
  • 1
  • 14
  • 27

1 Answers1

1

How should this be constructed so onclick events function as they do in the first method?

Uncaught TypeError: Object # has no method 'addEventListener'

That's obcously the reason. You need to add the event listenere to a DOM element, so you could do for example:

var clickMe = new CountMe();
document.getElementById("square").addEventListener("click", clickMe.countClick, false);

The variable elt is, as correctly commented, privately scoped and cannot be accessed from outside. That means you just should move the add-process into the constructor (if the element is determinable), or drop it at all.

In the method countClick what context is the nested this in? The instance of the CountMe class I suspect, just want someone else's take.

That depends on the calling. With your code

clickMe.countClick();

the instance clickMe would be the context, but when the function is called as an event listener the DOM element will be the context. See MDN's overview for the this keyword. You can use a closure-scoped variable to hold a reference to the actual instance, as for example described here (there are many questions about that).

Three possible quick-fixes:

  • domel.addEventListener("click", clickMe.countClick.bind(clickMe), false)
  • domel.addEventListner("click", function(){clickMe.countClick();}, false)
  • var that=this; this.countClick=function(){ that.addCount(); alert(); };
Community
  • 1
  • 1
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • I will give the links a look. I've updated my code example and now I get the following error `Uncaught TypeError: Object # has no method 'addCount'`. Can you fiddle a working answer based on your comment? – rhodee Jun 28 '12 at 22:15
  • Yes, that's now the problem/feature that the context is the DivElement not the CountMe instance. – Bergi Jun 28 '12 at 22:19
  • I have outlined the possible solutions, though probably you would have found and understood them yourself when reading about the problem. – Bergi Jun 28 '12 at 22:22
  • you're definitely right. I am coming from a different language and context functions a bit differently – rhodee Jun 29 '12 at 13:38