Model-View-Controller: Intro, HTML, loading files

What is Model-View-Controller?

The MVC design pattern splits an application into three separate entities, the views, which is what the user can see, the controller, which accepts events mainly from the views. Then there is the model, which collects and stores data, which are sent back to views.

MVC explanation
Fig.1 - The MVC pattern.

The MVC, which I introduce here may be named XMVC, because additionally an XML file with data is loaded, and the data are retrieved and stored in the model. The XML file can also serve as part of the data management to make changes in the HTML page.

The advantage of using a design pattern like MVC is that 1. we separate the whole application into different parts, 2. we can reuse certain functions and 3. we can communicate between the parts by using event dispatchers and listeners. Separating an application into small parts makes it easier for us to work and find errors instead of having one big script. We will have separate scripts for each view, for the controller and for the model. We will have a central document to initiate the application similar to the Document Class in Flash. Thus we can reuse functions in the controller and the model. Separation of the views from the controller and model fullfils another principle of programming, which is loose coupling. Instead of having strict coupling throughout an application by referring to functions directly, we use event dispatchers and listeners, which allow much higher flexibility.

Building the application

As an example I created a small application (view here) similar to a simple shop, which also includes a PHP file. This application consists of three different views, which are on top of each other and become visible when needed. View 1 is what we see when we open the application. Here the user can choose a certain product and will see an image, which can also be a video or something else. Then the user can select the product and view 2 appears, which is an order form. After the user has submitted the order, view 3 appears, which is a statement, whether the order was successful or not. The user can then exit or go back to the first view to see more products. Below the three views is a canvas drawing, which is framing the views. So first we need to create the three views with all its components. Below the views are shown.

	<div id="sketch">
			<canvas id="paint"></canvas>
			
<!-- The individual views follow. 'view1' is required to select the kind from an ad image. -->

		<div id="view1">
			<button id="iMG1"></button>
			<button id="iMG2"></button>
			<button id="iMG3"></button>
			<br><br>
			<img src="" id="selectIMG"/>
			<br>
			<button id="imgSelect">Order :</button>
			<input type="text" id="imgSelectText"/>
		</div>
		
<!-- 'view2' is an order form. -->

		<div id="view2">
			<form id="view2Form">
  				Order: <input id="order" type="text" name="ordertype" required="required"/>
  				<br><br>
  				Name: <input type="text" name="name" required="required" placeholder="Your Name"/>
  				<br><br>
  				Email: <input type="text" name="email" required="required" placeholder="Your email"/>
  				<br><br><br>
  				<input id="formsubmit"/> 
  				<input id="cancel"/>
			</form> 
		</div>
		
<!-- 'view3' appears after the order was sent and informs the user about the outcome. -->

		<div id="view3">
			<button id="anotherBut">Order another item.</button>
			<input type="text" id="formMes"/>
			<br><br>
			<img src="" id="formSuccess"/>
		</div>
		</div>
	

View 1 are three buttons to select products to purchase. You notice that we only give the id here, because the values like text and images will be provided externally by an XML file, when the page loads. Further, there is space for an image and beneath there is a button to select the product and a textfield with the name of the product. So if we have different products we make changes only in the XML file. View 2 is basically an order form, where the product is listed and input is retrieved from the user. The data will be sent to a PHP file. The we have a 'submit' and a 'cancel' button. The third view appears after the PHP file has been processed and shows an image and has text to state that the order was successful or not. Then there is a button to go back to the beginning. Each of the views has its own identity and its position is relative to the canvas. I am not discussing the css file in detail here. So now let's have a look at the header and footer of the HTML page.

	HEADER:
	<html>
	<head>
		<title>MVC Example</title>
		
<!-- LOADING STYLE SHEET -->

		<link rel="stylesheet" href="styles/eventdispatch.css" />
	</head>
	<body>
	
	FOOTER:
	<!-- Loading of all javascripts occurs at the bottom of the page preferably the footer -->

		<footer>
			<script type="text/javascript" src="src/loading.js"></script>
		</footer>
	</body>
</html>
	

In the header we have only the stylesheet loading. All Javascripts are loaded in the footer using loading.js There is some more script not shown here, which we will discuss later.

Loading all js files

Loading is done asychronously. Actually the order is only to some extent important, since instantiation of many of the classes occurs in the Documentclass, which must be the last class to be loaded. The abstractclass.js containg the Abstractclass has to be loaded first, since it is the superclass for many other classes. In the next section we discuss the Abstractclass and the individual views.

/* 
The loading script is from Jeremy Hixon 
(http://jeremyhixon.com/loading-javascript-files-asynchronously/).

===========================================================
Loading scripts anychronously

Usage: getScript('script.js', function() {callback});
============================================================
*/

function getScript(url,success)
{
	var script = document.createElement('script');
	script.src = url;
	var head = document.getElementsByTagName('head')[0], done=false;
	script.onload = script.onreadystatechange = function()
	{
		if (!done && (!this.readyState || this.readyState == 'loaded' || this.readyState == 'complete')) 
		{
			done=true;
			success();
			script.onload = script.onreadystatechange = null;
			head.removeChild(script);
		}
	};
	head.appendChild(script);
}
    
// Starting with the abstractclass.js all scripts are loaded in the order needed.

getScript('src/abstractclass.js', function() 
{
	getScript('src/interface.js', function() 
	{
		getScript('src/model.js', function() 
		{
			getScript('src/controller.js', function() 
			{
				getScript('src/view1.js', function() 
				{
					getScript('src/view2.js', function()
					{ 
						getScript('src/view3.js', function() 
						{
							getScript('src/EventBus.js', function()
							{
								getScript('src/documentclass.js', function(){});
							});
						});
					});
				});
			});
		});
	});
});
	

In the next section I will present the Abstractclass and the views.