A Simple Control Framework in JavaScript

The JavaScript code shown below declaratively creates a bunch of controls, converts them to DOM elements, and displays them. The displayed controls prompt the user for his or her name. The user may then click a button to receive a (very slightly) personalized greeting.

To see the code in action, copy it into an .html file and open that file in a web browser that runs JavaScript.

<html>
<body>
<script type='text/javascript'>

// main
function ControlTest()
{
	this.main = function()
	{
		var defns = ControlDefn.Instances;

		var controlRoot = new Control
		(
			"containerMain",
			defns.Container,	
			new Coords(0, 0), // pos
			new Coords(200, 300), // size
			// children
			[
				new Control
				(
					"labelName", 
					defns.Label, 	
					new Coords(20, 20), 	
					new Coords(100, 20), 	
					null, 
					[["text", "Name:"]]
				),
				new Control
				(
					"textBoxName", 	
					defns.TextBox, 	
					new Coords(20, 60), 	
					new Coords(100, 20),	
					null, 
					[["text", "Joe"]]
				),
				new Control
				(
					"buttonGreet", 	
					defns.Button, 	
					new Coords(20, 100), 	
					new Coords(100, 20), 	
					null, 
					[
						["text", "Say Hello" ], 
						[
							"onclick", 
							function(event) 
							{ 
								var buttonClicked = event.target.control;
								var parentContainer = buttonClicked.parent;

								var textBoxName = parentContainer.children["textBoxName"];
								var nameOfPersonToGreet = textBoxName.text;

								var greetingMessage = 
									"Hello, " 
									+ nameOfPersonToGreet
									+ "!";

								var labelGreeting = parentContainer.children["labelGreeting"];
								labelGreeting.text = greetingMessage;

								labelGreeting.updateHTMLElement();
							}
						],
					]
				),
				new Control
				(
					"labelGreeting", 	
					defns.Label, 	
					new Coords(20, 140), 	
					new Coords(100, 20), 	
					null, 
					[
						["text", "" ]
					]
				),
			]
		);

		var controlRootAsHTMLElement = controlRoot.toHTMLElement();

		document.body.appendChild(controlRootAsHTMLElement);
	}
}

// classes

function Control(name, defn, pos, size, children, propertyNameValuePairs)
{
	this.name = name;
	this.defn = defn;
	this.pos = pos;
	this.size = size;
	this.children = children;

	if (this.children != null)
	{
		for (var i = 0; i < this.children.length; i++)
		{
			var child = this.children[i];
			child.parent = this;
			this.children[child.name] = child;
		}
	}

	if (propertyNameValuePairs != null)
	{
		for (var i = 0; i < propertyNameValuePairs.length; i++)
		{
			var propertyNameValuePair = propertyNameValuePairs[i];
			var propertyName = propertyNameValuePair[0];
			var propertyValue = propertyNameValuePair[1];
			this[propertyName] = propertyValue;
		}
	}
}
{
	// html

	Control.prototype.toHTMLElement = function()
	{
		this.htmlElement = this.defn.toHTMLElement(this);

		return this.htmlElement;
	}

	Control.prototype.updateHTMLElement = function()
	{
		this.defn.updateHTMLElement(this);
	}
}

function ControlDefn(name, toHTMLElement, updateHTMLElement)
{
	this.name = name;
	this.toHTMLElement = toHTMLElement;
	this.updateHTMLElement = updateHTMLElement;
}
{
	// Instances

	ControlDefn.Instances = new ControlDefn_Instances();

	function ControlDefn_Instances()
	{
		this.Button = new ControlDefn
		(
			"Button", 
			function(control)
			{
				var returnValue = document.createElement("button");
				control.initializeHTMLElement(returnValue);
				returnValue.innerHTML = control.text;
				returnValue.onclick = control.onclick;
				return returnValue;
			}, 
			function(control){}
		);

		this.Container = new ControlDefn
		(
			"Container",
			function(control)
			{
				var returnValue = document.createElement("div");
				control.initializeHTMLElement(returnValue);

				for (var i = 0; i < control.children.length; i++)
				{
					var child = control.children[i];
					var childAsHTMLElement = child.toHTMLElement();
					returnValue.appendChild(childAsHTMLElement);
				}

				return returnValue;
			}, 
			function(control){}
		);

		this.Label = new ControlDefn
		(
			"Label",
			function(control)
			{
				var returnValue = document.createElement("p");
				control.initializeHTMLElement(returnValue);
				returnValue.innerHTML = control.text;
				return returnValue;
			}, 
			function(control)
			{
				control.htmlElement.innerHTML = control.text;
			}
		);

		this.NumberBox = new ControlDefn
		(
			"NumberBox",
			function(control)
			{
				var returnValue = document.createElement("input");
				control.initializeHTMLElement(returnValue);		
				returnValue.innerHTML = control.value;
				return returnValue;
			}, 
			function(control){}
		);

		this.SelectBox = new ControlDefn
		(
			"SelectBox",
			function(control)
			{
				var returnValue = document.createElement("select");
				control.initializeHTMLElement(returnValue);
				returnValue.innerHTML = "[selectBox]";
				return returnValue;
			}, 
			function(control){}
		);

		this.TextBox = new ControlDefn
		(
			"TextBox",
			function(control)
			{
				var returnValue = document.createElement("input");
				control.initializeHTMLElement(returnValue);
				returnValue.value = control.text;
				return returnValue;
			}, 
			function(control){} 
		);
	}

	// instance methods

	Control.prototype.initializeHTMLElement = function(htmlElementToInitialize)
	{
		htmlElementToInitialize.id = this.name;
		htmlElementToInitialize.style.position = "absolute";
		htmlElementToInitialize.style.left = this.pos.x;
		htmlElementToInitialize.style.top = this.pos.y;
		htmlElementToInitialize.style.width = this.size.x;
		htmlElementToInitialize.style.height = this.size.y;

		htmlElementToInitialize.control = this;
	}
}

function Coords(x, y)
{
	this.x = x;
	this.y = y;
}

// run

new ControlTest().main();

</script>
</body>
</html>
This entry was posted in Uncategorized and tagged , , . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s