Source: env/view/stubViewEngine.js


/**
 * Stub for view/rendering engine:
 *
 * mocks the function calls and invokes the hooks on the controllers without actually rendering anything.
 *
 *
 * @example
 * mmir.present.render('theController', 'theView');
 *
 * @class
 * @name StubViewEngine
 * @memberOf mmir.env.view
 * @static
 * @hideconstructor
 *
 *  @depends document (DOM object)
 *  @depends HTMLElement.parentElement
 *  @depends HTMLElement.removeChild
 *
 */
define(['mmirf/logger', 'mmirf/util/deferred', 'module'],function(Logger, Deferred, module){

	var log = Logger.create(module);

	var promise = new Deferred();

	//property names for passing the respected objects from doRenderView() to doRemoveElementsAfterViewLoad()
	var FIELD_NAME_RESOLVE 		 = '__renderResolve';
	var FIELD_NAME_VIEW 		 = '__view';
	var FIELD_NAME_DATA 		 = '__renderData';
	var FIELD_NAME_CONTROLLER 	 = '__ctrl';
	var FIELD_NAME_MANAGER 	 = '__present';

	//function for removing "old" content from DOM (-> remove old, un-used page content)
	var doRemoveElementsAfterViewLoad = function(_event, data){

		var presentMgr = data[FIELD_NAME_MANAGER];
		var ctrl = data[FIELD_NAME_CONTROLLER];
		var view = data[FIELD_NAME_VIEW];
		var renderData = data[FIELD_NAME_DATA];
		var defer = data[FIELD_NAME_RESOLVE];

		//FIX handle missing ctrl/view parameter gracefully
		//     this may occur when doRemoveElementsAfterViewLoad is
		//     triggered NOT through doRenderView but by some automatic
		//	   mechanism, e.g. BACK history event that was not handled
		//	   by the framework (which ideally should not happen ...)
		var viewName;
		if(view){
			viewName = view.getName();
		}

		if(!ctrl){
			log.e('PresentationManager[stubViewEngine].__doRemoveElementsAfterViewLoad: missing controller (and view)!',data.options);
			return;
		}

		log.d('on_page_load::'+viewName, renderData);

		//trigger "after page loading" hooks on controller:
		// the hook for all views of the controller MUST be present/implemented:
		presentMgr._fireRenderEvent(ctrl, 'on_page_load', renderData, viewName, renderData);
		//... the hook for single/specific view MAY be present/implemented:
		if(view){
			presentMgr._fireRenderEvent(ctrl, 'on_page_load_'+viewName, renderData);
		}

		defer.resolve();
	};

	/**
	 * Actually renders the View.<br>
	 * Fetches the layout for the controller, then fills the
	 * layout-template with the view content, while incorporating
	 * partials and contents that helper methods have provided. Then
	 * Dialogs are created and the pageContainer id is updated. At last
	 * all the content is localized using
	 * {@link mmir.LanguageManager#translateHTML}, and appended to
	 * the HTML document of the application, while the old one is
	 * removed.<br>
	 * At the end the <b>on_page_load</b> action is performed.
	 *
	 * @function doRenderView
	 *
	 * @param {String}
	 *            _ctrlName Name of the controller
	 * @param {String}
	 *            viewName Name of the view to render
	 * @param {Object}
	 *            view View object that is to be rendered
	 * @param {Object}
	 *            ctrl Controller object of the view to render
	 * @param {Object}
	 *            [data] optional data for the view.
	 * @returns {Promise}
	 * 	        	a Promise that gets resolved when rendering is finished
	 *
	 * @memberOf mmir.env.view.StubViewEngine#
	 */
	var doRenderView = function(_ctrlName, viewName, view, ctrl, data){

		//if set to FALSE by one of the hooks (ie. before_page_prepare / before_page_load)
		//   will prevent rendering of the view!
		var isContinue;

		log.d('before_page_prepare::'+viewName, data);

		//trigger "before page preparing" hooks on controller, if present/implemented:
		isContinue = this._fireRenderEvent(ctrl, 'before_page_prepare', data, viewName, data);
		if(isContinue === false){
			return;/////////////////////// EARLY EXIT ////////////////////////
		}

		isContinue = this._fireRenderEvent(ctrl, 'before_page_prepare_'+viewName, data);
		if(isContinue === false){
			return;/////////////////////// EARLY EXIT ////////////////////////
		}

		// var layout = this.getLayout(ctrlName, true);

		var renderResolve = new Deferred();
		var presentMgr = this;
		var renderFunc = function(){

			//provide "change" data for before_page_load calls:
			var pageEvtData = {
				name: viewName
			};

			log.d('before_page_load::'+viewName, pageEvtData);

			//trigger "before page loading" hooks on controller, if present/implemented:
			isContinue = presentMgr._fireRenderEvent(ctrl, 'before_page_load', data, pageEvtData);//<- this is triggered for every view in the corresponding controller
			if(isContinue === false){
				return;/////////////////////// EARLY EXIT ////////////////////////
			}

			isContinue = presentMgr._fireRenderEvent(ctrl, 'before_page_load_'+viewName, data, pageEvtData);
			if(isContinue === false){
				return;/////////////////////// EARLY EXIT ////////////////////////
			}

			//pass controller- and view-instance to "after page change" handler
			var changeOptions = {};
			changeOptions[FIELD_NAME_RESOLVE] = renderResolve;
			changeOptions[FIELD_NAME_VIEW] = view;
			changeOptions[FIELD_NAME_DATA] = data;
			changeOptions[FIELD_NAME_CONTROLLER] = ctrl;
			changeOptions[FIELD_NAME_MANAGER] = presentMgr;

			doRemoveElementsAfterViewLoad.call(null,{},changeOptions);
		};

		renderFunc();
		return renderResolve;
	};

	promise.resolve({
		/**
		 * @copydoc mmir.env.view.StubViewEngine#doRenderView
		 * @function render
		 * @public
		 *
		 * @memberOf mmir.env.view.StubViewEngine.prototype
		 * @see mmir.PresentationManager#render
		 */
		render: doRenderView,
		/**
		 * Closes a modal window / dialog.<br>
		 *           *
		 * @function hideCurrentDialog
		 * @public
		 *
		 * @memberOf mmir.env.view.StubViewEngine.prototype
		 * @see mmir.PresentationManager#hideCurrentDialog
		 */
		hideCurrentDialog : function() {
							//stub: do nothing
							log.i('hideCurrentDialog');
		},
		/**
		 * Opens the requested dialog.<br>
		 *
		 * @function showDialog
		 * @param {String}
		 *            _ctrlName Name of the controller
		 * @param {String}
		 *            _dialogId Id of the dialog
		 * @param {Object}
		 *            _data Optionally data - not used
		 *
		 * @returns {Object} the instance of the current dialog that was opened
		 *
		 * @public
		 *
		 * @memberOf mmir.env.view.StubViewEngine.prototype
		 * @see mmir.PresentationManager#showDialog
		 */
		showDialog : function(_ctrlName, _dialogId, _data) {
						//stub: do nothing
						log.i('showDialog');
		},

		/**
		 * Shows a "wait" dialog, i.e. "work in progress" notification.
		 *
		 * @function showWaitDialog
		 *
		 * @param {String} [_text] OPTIONAL
		 * 				the text that should be displayed.
		 * 				If omitted the language setting for <code>loadingText</code>
		 * 				will be used instead (from dictionary.json)
		 * @param {String} [_theme] OPTIONAL
		 * 				set the jQuery Mobile theme to be used for the wait-dialog
		 * 				(e.g. "a" or "b").
		 * 				NOTE: if this argument is used, then the <code>text</code>
		 * 					  must also be supplied.
		 *
		 * @public
		 *
		 * @see #hideWaitDialog
		 *
		 * @memberOf mmir.env.view.StubViewEngine.prototype
		 * @see mmir.PresentationManager#showWaitDialog
		 */
		showWaitDialog : function(_text, _theme) {
			//stub: do nothing
			log.i('showWaitDialog');
		},

		/**
		 * Hides / closes the "wait" dialog.
		 *
		 * @function hideWaitDialog
		 * @public
		 *
		 * @see #showWaitDialog
		 *
		 * @memberOf mmir.env.view.StubViewEngine.prototype
		 * @see mmir.PresentationManager#hideWaitDialog
		 */
		hideWaitDialog : function() {
			//stub: do nothing
			log.i('hideWaitDialog');
		},
	});

	return promise;
});