Reputation: 564
I was hoping someone would be able to tell me why calling TestProtObj.init isn't working as expected - the listener is not working all.
$(document).ready(function () {
//set TestProtObj properties in the constructor
var TestProtObj = function (string, target, button) {
this.testValue = string;
this.target = $(target);
this.button = $(button);
}
//add methods to the object prototype
TestProtObj.prototype = {
init: function () {
this.button.on('click', function (e) {
e.preventDefault;
this.returnTest();
});
},
returnTest: function () {
this.target.append(this.testValue);
}
}
//initialize client code
var testString = 'It worked!',
targetDiv = '#target',
button = 'button.text-button';
//call the returnTest() method and pass in params above
var TestConcObj = new TestProtObj(testString, targetDiv, button);
TestConcObj.init();
});
Strangely, the following code works:
$(document).ready(function () {
var bindListener = function () {
$('.test').on('click', function (e) {
e.preventDefault;
$('.target').append('It works!');
})
}
bindListener();
})
It seems that putting the function into an object literal is for some reason, causing it to fail. No errors are being thrown in the Chrome debug toolbar.
Help greatly appreciated.
JSFiddles:
Upvotes: 2
Views: 960
Reputation: 564
I have figured it out. I was trying .live() until I stupidly realised it had been deprecated. Anyone who is trying what I tried should use the technique found in the jQuery docs, with the following snippet:
AjaxProt.prototype = {
init: function () {
var thisObj = this;
$(document).on(thisObj.event, thisObj.targetEl, function(e) {
e.preventDefault();
thisObj.ajaxCall();
});
},
This will prevent jQuery from attempting to bind the listener on a non-existent element (that is dynamically loaded) until it actually comes into existence - by quite cleverly making use of the $(document)
global object.
I hope this saves someone half a day of debugging as I have just attempted to stupidly do. Cheers!
Edit: Thanks to Mouser and all the others who tried to help me overcome my own stupidity.
Upvotes: 0
Reputation: 662
Your class is not properly coded. Try this:
var TestProtObj = function TestProtObj(string, target, button) {
return this.prototype.init.call(string, target, button, this);
}
TestPrtoObj.prototype.testValue = null;
TestPrtoObj.prototype.target = null;
TestPrtoObj.prototype.button = null;
TestProtObj.prototype.init = function init(string, target, button) {
vat self = this;
this.testValue = string;
this.target = $(target);
this.button = $(button);
this.button.on('click', function (e) {
e.preventDefault;
self.returnTest();
});
return this;
}
TestProtObj.prototype.returnTest = function returnTest() {
this.target.append(this.testValue);
}
//initialize client code
var testString = 'It worked!',
targetDiv = '#target',
button = 'button.text-button';
//call the returnTest() method and pass in params above
var instance = new TestProtObj(testString, targetDiv, button);
The init method is automatically called when you create a new instance. Now the button should be responding to the click event.
Check this awesome tutorial to get more information: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Introduction_to_Object-Oriented_JavaScript
I recommend naming the functions, this will help you when debugging, you will see the name of your function in the stack trace instead of just [Function] or [Function anonymous] if an exception is thrown.
Hope this helps.
Upvotes: 0
Reputation: 13304
Just create a private variable inside this function, that refers to the TestProtObj
inside the init function using the keyword this
. You can reuse this variable (self
) during the entire scope of the function init
.
init: function () {
var self = this;
this.button.on('click', function (e) {
e.preventDefault(); //add () here.
self.returnTest();
});
Because JavaScript uses lexical scope
this will work.
https://jsfiddle.net/p9fjamz3/14/
When you refer to this inside the event handler this.button.on('click', ...
you actually are referring to the button and not to your object.
Upvotes: 2