Jump to content

Problem referring to 'this'


ShadowMage

Recommended Posts

I've created a custom dialog and I'm trying to apply a function to the button. Here's the relevant portions of the code:

function CustomDialog(elemID) {	this.dialog = document.getElementById(elemID);	...	this.alert = function(msg, title, pos, func) {		if (dlgContainer) {			...			if (dlgButtons.count > 0) {				if (func !== undefined) {					dlgButtons.Btn0.onclick = func;				} else if (typeof(pos) == 'function') {					dlgButtons.Btn0.onclick = pos;				} else {					dlgButtons.Btn0.onclick = function() { this.hide(); };				}			}		}		...	};		this.hide = function() {		this.dialog.style.display = "none";	}}

The line giving me trouble is:dlgButtons.Btn0.onclick = function() { this.hide(); };I keep getting the error: this.hide() is not a functionin FireBug.I've tried this a couple different ways:dlgButtons.Btn0.onclick = function() { this.dialog.style.display = "none"; };dlgButtons.Btn0.onclick = function() { document.getElementById(elemID).dialog.style.display = "none"; };Nothing seems to work. How can I do this? I think I can use the apply method of the Function object but I just can't wrap my mind around how to even try to use it... :)

Link to comment
Share on other sites

I ran into a similar problem like this at work recently when dealing with calling a class method when working within a callback provided onreadystatechange function (all while in the class). My co-worker and I couldn't figure it out so I had to make a global reference to this within the class itself. In your case, try:

function CustomDialog(elemID) {	this.dialog = document.getElementById(elemID);	var classRef = this;  //create a global reference to the function scoped within itself	...	this.alert = function(msg, title, pos, func) {		if (dlgContainer) {			...			if (dlgButtons.count > 0) {				if (func !== undefined) {					dlgButtons.Btn0.onclick = func;				} else if (typeof(pos) == 'function') {					dlgButtons.Btn0.onclick = pos;				} else {					//use the reference to the class here to access the method					dlgButtons.Btn0.onclick = function() { classRef.hide(); };				}			}		}		...	};		this.hide = function() {		this.dialog.style.display = "none";	}}

Link to comment
Share on other sites

yeah, its kinda hacky I know, but it worked for my application. It must be a scoping issue wherein the scope of the button who's methods you are calling are within the document scope, and that's where it's trying to call this.hide() from, as opposed to the scope of CustomDialog().

Link to comment
Share on other sites

yeah, its kinda hacky I know, but it worked for my application. It must be a scoping issue wherein the scope of the button who's methods you are calling are within the document scope, and that's where it's trying to call this.hide() from, as opposed to the scope of CustomDialog().
Yeah, I agree, it's a little quirky, but it does work. I've looked at the source code for jQuery (just to see if I can figure it out :) ) and it uses the apply method of the Function to do this. And the documentation in that link seems to imply that this the intended use of apply. However, when I've tried to write it out myself, I just can't seem to get a grasp on how it should be written.
Link to comment
Share on other sites

The trick is that this is not a normal variable. If you embed a normal variable (not a global) in an anonymous function, what gets embedded is the value. When you copy this to classRef, you are now able to embed the value of this (rather, a reference to the object that this points to).this by itself won't do that. When you use this in the anonymous function, you are not embedding a reference to the original object. this does what it always does (point to the parent object in the current scope). That would be dlgButtons.Btn0, which does not have a hide method.I don't think that's hacky at all.

Link to comment
Share on other sites

BACKWARD.I READTHINKENGINEERSHIGHWAY
:)
The trick is that this is not a normal variable. If you embed a normal variable (not a global) in an anonymous function, what gets embedded is the value. When you copy this to classRef, you are now able to embed the value of this (rather, a reference to the object that this points to).this by itself won't do that. When you use this in the anonymous function, you are not embedding a reference to the original object. this does what it always does (point to the parent object in the current scope). That would be dlgButtons.Btn0, which does not have a hide method.I don't think that's hacky at all.
Well, when you put it that way it makes more sense. Thanks for the explanation, DD.
Link to comment
Share on other sites

see, I was sure that this only worked within the scope of the nearest opening { but my co-worker was adamant that it should have worked the way that is being tried here, in spite of not being able to actually get it to work that way himself, haha.

Link to comment
Share on other sites

Your coworker's assumption was at least reasonable, since any other variable would have worked like that. Only problem, this isn't really a variable. If it were, you could write things like this=5, which actually throws a parsing error.Tricky concept, this. Everyone calls it a keyword, which says nothing about it. The mozilla site calls it an operator, which seems close but not quite it. PHP calls $this a pseudo-variable. That almost does it.

Link to comment
Share on other sites

Tricky concept, this. Everyone calls it a keyword, which says nothing about it. The mozilla site calls it an operator, which seems close but not quite it. PHP calls $this a pseudo-variable. That almost does it.
It is indeed tricky. I've fallen into many a pitfall with trying get correct scoping when using this.BTW, I did get the apply method to finally work!
function CustomDialog(elemID) {	this.dialog = document.getElementById(elemID);	var me = this;	...	this.alert = function(msg, title, pos, func) {		if (dlgContainer) {			...			if (dlgButtons.count > 0) {				if (func !== undefined) {					dlgButtons.Btn0.onclick = func;				} else if (typeof(pos) == 'function') {					dlgButtons.Btn0.onclick = pos;				} else {					dlgButtons.Btn0.onclick = function() { me.hide(); };				}			}		}		showDialog.apply(this, null);	};	...	this.hide = function() {		this.dialog.style.display = "none";		document.body.style.overflow = initOverflow;	}		function showDialog() {		this.dialog.style.display = "block";		document.body.style.overflow = "hidden";		if (dlgButtons.count > 0) {			dlgButtons.Btn0.focus();		}	}	...}

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...