Page 1 of 1

JavaScript handling of "this" pointer

Posted: Tue Jan 02, 2007 5:38 am
by Chris Corbyn
I'm re-writing an old windows-style "Start" menu I made some time ago. I want the onclick property of the menu to call a different function each time it's clicked (i.e. a toggle) but this is getting its knickers in a twist saying that "this.mask" has no properties. Can anybody tell me why? This always confuses me; JavaScript does some funny things with exactly what "this" points to inside non-literal objects.

The reveal() method is called as expected, but it throws an error that mask() has no properties. I tried changing it to read the state of the domData property but equally, it says that domData has no properties.

Code: Select all

/**
 * Builds a clickable tree-menu system which can be appended to an existing DOM node
 * @constructor
 * @param {int} Position from bottom of screen in pixels
 * @param {int} Position from left of screen in pixels
 */
function CompositeClickMenu(bottomPos, leftPos)
{
	this.domData;
	this.bottom = bottomPos;
	this.left = leftPos;
	
	/**
	 * Initialize the DOM node
	 * @param {CompositeClickMenu} This instance
	 */
	var init = function(o)
	{
		o.domData = document.createElement("div");
		o.domData.id = "_ClickMenu" + (++CompositeClickMenu.instances).toString();
		o.domData.style.position = "absolute";
		o.domData.style.bottom = o.bottom;
		o.domData.style.left = o.left;
		o.domData.style.backgroundColor = "#7777ff";
		o.domData.style.width = "100px";
		o.domData.style.height = "20px";
		o.domData.style.cursor = "pointer";
		o.domData.style.fontWeight = "bold";
		o.domData.style.color = "#ffffff";
		o.domData.style.textAlign = "center";
		o.domData.innerHTML = "CLICK";
		
		o.domData.onclick = o.reveal;
	}
	this.mask = function()
	{
		//
		alert("mask");
	}
	this.reveal = function()
	{
		//
		alert("reveal");
		this.domData.onclick = this.mask;
	}
	/**
	 * Append this DOM node to part of the DOM-tree
	 * @param {Element} The existing node to append to
	 * @returns boolean
	 */
	this.attachTo = function(node)
	{
		try {
			node.appendChild(this.domData);
			return true;
		} catch (e) {
			return false;
		}
	}
	//Run constructor
	init(this);
}
/**
 * Factory method for convenience creating new instances
 * @static
 * @param {int} Posisition from bottom of screen in pixels
 * @param {int} Posiition from left of screen in pixels
 * @returns CompositeClickMenu
 */
CompositeClickMenu.newInstance = function(bottomPos, leftPos)
{
	var instance = new CompositeClickMenu(bottomPos, leftPos);
	return instance;
}
/**
 * The number of instances present on this page
 * @static
 * @type Integer
 */
CompositeClickMenu.instances = 0;

Code: Select all

<html>
<head>
<script type="text/javascript" src="CompositeClickMenu.js"></script>
<title>CompositeClickMenu Test</title>
</head>
<body>

<div id="menuBar" style="
	position: absolute;
	bottom: 0;
	left: 0;
	background: #aaaaaa;
	height: 20px;">
	<span style="float: right;">Foobar</span>
	<span id="clickButton"></span>
</div>

<script type="text/javascript">
<!-- Hide

var mainMenu = CompositeClickMenu.newInstance(0, 0);
mainMenu.attachTo(document.getElementById("clickButton"));

// End -->
</script>

</body>
</html>
EDIT | Weirdan's usual magic trick of copying "this" worked

Code: Select all

	var me = this;

// snip //

	this.reveal = function()
	{
		//
		alert("reveal");
		me.domData.onclick = me.mask;
	}
:?

Posted: Tue Jan 02, 2007 8:41 am
by feyd
What about using the prototype property? Right now you're technically building a dynamic class/object. With the prototype property it generates a new class, if memory serves. (It's been a while since I've done any serious Javascript.)

Posted: Tue Jan 02, 2007 9:13 am
by Chris Corbyn
I'm not sure how you mean? You use prototype as a static property of the class itself but I thought the only things it could do were add new members or provide a chained object (icky-yucky inheritance).

Posted: Tue Jan 02, 2007 9:24 am
by feyd
You're right, I must have been thinking of something else. Prototype is for modifying an existing class.