Model-View-Controller: Controller and Model

Controller

The Controller has several event listeners. If one event like the 'submit' event is the same for several different events, this is differentiated by the identification of the DOM element. Also values for the elements are retrieved.

/*========================================================
The Controller class receives events dispatched from the document
and has listeners. Here the individual events will be further
processed and sent to the Model class.
*/

var Controller = function (aModel)
{
	var md = aModel;
	
// The listener for all the button clicks

	EventBus.addEventListener("click", getButEvent, this);
	function getButEvent (event, imgvalue)
	{
		var butId = imgvalue.target.id;
		var butValue = imgvalue.target.value;
		if(butId == "imgSelect")
		{
			md.selectView2 (butValue, "imgSelect");
			doc.showView("hideView1");
		}
		else if (butId == "anotherBut")
		{
			doc.showView ("hideView2");
			
/*===== Enter your url here for reloading. =======================================*/

			location.replace ("http://your_url.com/mvcexample.html");
		}
		else if (butId == "cancel")
		{
			md.cancelOrder();
			doc.showView("hideView2");
		}
		else
		{
			md.fillImg(butId);
		}
	}
	
	EventBus.addEventListener ("submit", submitButEvent, this);
	function submitButEvent (event)
	{
		md.submitOrder();
	}
	
	EventBus.addEventListener("resultForm", formEvent, this);
	function formEvent (event, formResult, formMessage)
	{
		if (formResult == "Okay")
		{
			md.afterForm (event, formMessage, "assets/Success.png");
		}
		else if (formResult == "Failed")
		{
			md.afterForm (event, formMessage, "assets/Failed.png");
		}
	}
}
	

The Controller has one parameter for an instance of the Model class. Actions in the Controller is to send either data to the Model class, for example 'md.selectView2 (butValue, "imgSelect");', or induce changes like hiding - showing views, for example 'doc.showView("hideView2");'. Using event dispatcher - listener makes the relation between the views and the Controller loose, which is one of the important principles in programming.

Model

From the Controller data are sent to the Model class, where those data are further processed and can be retrieved from the views for update. Initially the individual event types are listed here as constants. Next there is a function to load the XML file, xhttp.onreadystatechange = function(). Once the file is loaded, data from the file can be retrieved. Since data in an XML file are like arrays, the data can be stored in an object array. Those are the text and URLs for the images.(

/*========================= Model class ===========================================
In this class data are collected, processed and sent back to the views by the update 
function. If this function is missing, an error will be thrown, since the Model class
inherits from the Abstractclass. Listed also are constants for the individual event
types.
===================================================================================*/

var Model = function ()
{

// Event Types

	const INIT_VIEW = "initView";
	const FILLED_IMG = "filledImg";
	const SELECT_VIEW = "selView";
	const SUBMIT_ORDER = "submitOrder";
	const CANCEL_ORDER = "cancelOrder";

// Here we retrieve data from the XML file to send back to view 1.

  	var parsexml = function (xml) 
	{
	
// We declare a variable for the XML file to get to the data later.

    	var xmlDoc = xml.responseXML;

// Data are stored in an array.

		var itemArray = [];
		this.itemArray = itemArray;
		for (var b = 0; b < xmlDoc.getElementsByTagName("item").length; b++)
		{
			var myitem = xmlDoc.getElementsByTagName("item")[b].childNodes[0].nodeValue;
			var myimage = xmlDoc.getElementsByTagName("image")[b].childNodes[0].nodeValue;
			itemArray.push({item:myitem, image:myimage});
		}
	}
	
// We need to create a variable holding the Model class.
	
	var itsme = this;
	
// Sending the request to load the XML file
	
	var xhttp = new XMLHttpRequest();
	xhttp.onreadystatechange = function() 
	{
    	if (xhttp.readyState == 4 && xhttp.status == 200) 
    	{
        	var p = new parsexml(xhttp);
        	var d = p.itemArray;

        	// The update function is triggered.
        	
        	itsme.update("initView", d);
    	}
	}
	xhttp.open("GET", "assets/choices.xml", true);
	xhttp.send();

Once the XML file is parsed and the array filled (if (xhttp.readyState == 4 && xhttp.status == 200) ), the data can be sent out using the update function.

/* 
The 'update' function dispatches an event to update specific views. The
event is not specific for the Model class but for the document.
*/

	this.update = function (evType, message, objt)
	{
		if (evType != null)
		{
			var mmes = new Mymessage ();
			mmes.setMes(message);
			this.mmes = mmes;
			var mobj = new Myobject ();
			mobj.setObject(objt);
			this.mobj = mobj;
			var evtp = new Myevent(evType);
			this.evtp = evtp;
			var cusEvent = new Event(evType);
			EventBus.dispatch (evType, this);
		}
	}

The update function has three parameters, for the event type, and two data types, If the event type is not null, several setters are instantiated. This makes sure, that the views can get the new data by calling the corresponding Model getters. Then an event is dispatched. As you will see later, event listeners are in the Document class triggering the update of views.

// Getter and Setter functions to hold data

    var Myevent = function (){}
    Myevent.prototype.setEvent = function(evt)
    {
        this.eventType = evt;
    }
    Myevent.prototype.getEvent = function()
    {
        return this.eventType;
    }
    Model.prototype.Myevent = function (){}
    
/*==========================================*/

    var Myobject = function (){}
    Myobject.prototype.setObject = function(obj)
    {
        this.objName = obj;
    }
    Myobject.prototype.getObject = function()
    {
        return this.objName;
    }
    Model.prototype.Myobject = function (){}
    
/*==========================================*/

	var Mymessage = function(){}
	Mymessage.prototype.setMes = function(mess)
    {
    	this.message1 = mess;
    }
    Mymessage.prototype.getMes = function()
    {
    	return this.message1;
    }
	Model.prototype.Mymessage = function (){}

Then there are the written out setter - getter functions. Finally the individual functions to update the views are added. They are all the update function with at least the event type as one parameter or additionally data.

/*==========================================
Function adds an image. 
*/

	Model.prototype.fillImg = function(ob)
	{
		var p = new parsexml(xhttp);
		this.update("filledImg", p.itemArray, ob);
	}

/*==========================================
Function adds a message to input field and 
view visibility changes. 
*/

	Model.prototype.selectView2 = function(bv, ob)
	{
		this.update("selView", bv, ob);
	}
	
/*==========================================
Function triggered, when the 'cancer' buttonis
is pressed. 
*/

	Model.prototype.cancelOrder = function()
	{
		this.update("cancelOrder", "Cancel");
	}

/*==========================================
Function triggered, when the 'submit' button 
is pressed. 
*/

	Model.prototype.submitOrder = function()
	{
		this.update("submitOrder", "Submit");
	}

/*==========================================
Function is triggered, when the php form is 
processed. 
*/

	Model.prototype.afterForm = function(event, fr, img)
	{
		this.update (event, fr, img);
	}
}

If data had to be processed further like calculations or string operations, this would be done by the Model class. Therefore, the data handling is done in the back of the application by the Model class. This separation of tasks makes working with large applications handy, since new views can be easily be added without touching already existing code. In the next section the Document class is discussed.