Source: modules/mvc/Controller.jsxinc

BX.use('brixy', 'modules/es/types.jsxinc');

/**
* @module 'brixy.mvc.Controller'
*/
BX.module.define('brixy.mvc.Controller', function() {
	var types = BX.module('brixy.es.types');
	
	/**
	* Base Controller object.
	* @class
	* @alias module:'brixy.mvc.Controller'~Controller
	*/
	function Controller() {
		this._renderConfig = {
			view: null,
			params: null
		};
	}
	
	/**
	* Returns a string representation of the object.
	* @method
	* @return {string}
	*/
	Controller.prototype.toString = BX.toString;

	/**
	* Sets the view and params.
	* @param {View|string} view
	* @param {...*} [arg1, arg2, ...] - Parameters will be passed to `view.render()` method. (optional)
	*/
	Controller.prototype.setView = function(view /*, arg1, arg2, ... */) {
		if (!view) {
			this._renderConfig.view = null;
			this._renderConfig.params = null;
			return;
		}

		this._renderConfig.view = view;
		this._renderConfig.params = (arguments.length > 1) ? [].slice.call(arguments, 1) : null;
	};
	
	/**
	* Returns controller's view.
	* @return {Object}
	*/
	Controller.prototype.getView = function() {
		var c = this._renderConfig;
		if (types.isString(c.view))
			c.view = new (BX.module.Me(c.view))();
			
		return c.view;
	};
	
	/**
	* Returns parameters that will be passed to the view.
	* @return {Array}
	*/
	Controller.prototype.getRenderParams = function() {
		return this._renderConfig.params;
	};
	
	/**
	* Renders the view.  
	* View class has to define a render method:  
	* `View.prototype.render = function(arg1, ar2, ...) {...; return 'nextControllerHandlerName';}`
	* 
	* @return {string} - Returns the name of next handler method as a result of the view.render() method.
	* @throws Exception
	*/
	Controller.prototype.renderView = function() {
		var r,
			view;
		
		try {
			view = this.getView();
			if (!view)
				return '';
			
			r = view.render.apply(view, this.getRenderParams());
		}
		catch (e) {
			if (view) {
				if (!('render' in view))
					r = 'View ' + view + '.render() method is not defined.';
				else
					r = 'View ' + view + '.render() error.';
			}
			else
				r = 'Cannot create a view.';
			throw BX.error('brixy.mvc.Controller.renderView()', Error(r), e);
		}
		
		return r;
	};
	
	/**
	* Runs the action.  
	* Subclass has to define a method for each action:  
	* `Ctrl.prototype.actionName = function(data) {...};`
	* 
	* @param {string} [action='Default'] - Controller's action. (optional)
	* @param {*} [data] - Action data. (optional)
	* @return {string|Object} - Next application request.
	* @throws Exception
	*/
	Controller.prototype.run = function(action, data) {
		var h,
			v,
			act = (action ? 'action' + action : 'actionDefault'),
			next = '';
		
		try {
			try {
				// process action
				next = this[act](data);
			}
			catch (e) {
				var er;
				if (act in this)
					er = 'Action ' + this.toString() + '.' + act + '() failed.';
				else
					er = this.toString() + '.' + act + '() method is not defined.';
				throw BX.error('brixy.mvc.Controller.run()', Error(er), e);
			}
			
			// show view
			v = this.getView();
			if (v) {
				h = this.renderView();
				if (h) {
					// process handler
					// (we have to pass the same view as rendered (prevent accidental change of the view in render method))
					next = this.processHandler(h, v) || next;
				}
			}
			this.setView(null); // clear a render config (view and params)
		}
		catch (e) {
			throw BX.error('brixy.mvc.Controller.run()', Error('Controller ' + this.toString() + ' failed. '), e);
		}
		
		return next;
	};
	
	/**
	* Runs the controller's handler.  
	* Subclass has to define a method for each handler:  
	* `Ctrl.prototype.handleName = function(view) {...};`
	* 
	* @param {string} handler - Handler name.
	* @param {Object} view
	* @return {string} - Result of handler.
	* @throws Exception
	*/
	Controller.prototype.processHandler = function(handler, view) {
		if (!handler)
			return '';
			
		handler = 'handle' + handler;
		
		try {
			return this[handler](view);
		}
		catch (e) {
			var er;
			if (handler in this)
				er = 'Handler ' + this.toString() + '.' + handler + '() failed.';
			else
				er = handler + '() method is not defined.';
			throw BX.error('brixy.mvc.Controller.' + handler + '()', Error(er), e);
		}
	};
	

	// publish the class
	return {
		/** 
		* Base controller class.
		* @memberOf module:'brixy.mvc.Controller'
		* @type {module:'brixy.mvc.Controller'~Controller}
		*/
		Me: Controller
	};
});