UNPKG

mmir-lib

Version:

MMIR (Mobile Multimodal Interaction and Relay) library

441 lines (382 loc) 13.9 kB
define ( [ 'mmirf/commonUtils', 'mmirf/helper', 'mmirf/logger', 'module' ], function ( commonUtils, Helper, Logger, module ){ /** * @private * @type mmir.tools.Logger * @memberOf mmir.ctrl.Controller# * @inner * @member logger */ var logger = Logger.create(module); /** * The Controller Class is a kind of interface-class which gives access to the methods of a controller and its helper. <br> * Also holds information about views and partials associated with the controller. * * @constructor * @class * @name Controller * @memberOf mmir.ctrl * @param {String} name Name of the Controller * @param {Object} jsonDef Information about the controllers, views, and partials * @param {Function} instanceConstr the constructor for creating a new controller instance * */ function Controller(name, jsonDef, instanceConstr){ // console.log("controller name " + name); /** * The json definition of the views and partials associated with the controller. Also contains paths to controller and its views/partials. * * @type Object * @public * @memberOf mmir.ctrl.Controller# * @member def */ this.def = jsonDef; /** * The name of the controller. * * @type String * @public * @memberOf mmir.ctrl.Controller# * @member name */ this.name = name; var viewDefs = this.def.views; /** * An array holding the names of all views associated with the controller. * * @type Array<String> * @public * @memberOf mmir.ctrl.Controller# * @member views */ this.views = []; this.parseViews(viewDefs); // parsing the partials and saving the names in an array var partialDefs = this.def.partials; /** * An array holding the names of all partials associated with the controller. * * @type Array<String> * @public * @memberOf mmir.ctrl.Controller# * @member partials */ this.partials = []; this.parsePartials(partialDefs); /** * The instance of the with the controller associated helper. * * @type mmir.ctrl.Helper * @public * @memberOf mmir.ctrl.Controller# * @member helper */ this.helper; /** * The layout (info) for this controller (if undefined, the default layout should be used) * @type Object * @memberOf mmir.ctrl.Controller# * @member layout */ this.layout = this.def.layout; /** * The definition of the controller object, i.e. its (application specific) implementation, * containing all properties and functions of the controller.<br> * * A method of the controller implementation can be called via: * <pre> * this.instance.method(parameter); * </pre> * * @type Object * @protected * @memberOf mmir.ctrl.Controller# * @member impl */ this.impl = new instanceConstr(this); /** * @deprecated use {@link #impl} instead * @protected * @memberOf mmir.ctrl.Controller# * @member script */ this.script = this.impl; } /** * This function loads the helper of the controller - if it exists. * * @function loadHelper * @param {String} name Name of the Helper to be loaded * @param {String} helperPath Path to the helper file to load * @param {Object} ctx the context for the helper implementation, i.e. where the constructor (will) exists: ctx.<helper name>() * @protected * @memberOf mmir.ctrl.Controller# */ Controller.prototype.loadHelper = function(name, helperPath, ctx){ if(typeof ctx[name] === 'function' && ctx[name].name === name){ //helper implementation was already loaded -> immediately create helper if(logger.isVerbose()) logger.v("[HELPER] already loaded "+name);//debug self.helper = new Helper(self, name, ctx[name]); } var self = this; if(typeof WEBPACK_BUILD !== 'undefined' && WEBPACK_BUILD){ helperPath = 'require://' + helperPath.replace(/\.js/i, ''); } else { //TODO move check of helper existence to Controller.foundControllersCallBack ? //determine if there is a helper for the controller: var path = helperPath; var fileName = path; var lastPathSeparatorIndex = path.lastIndexOf('/'); if(lastPathSeparatorIndex !== -1){ path = path.substring(0,lastPathSeparatorIndex); fileName = fileName.substring( lastPathSeparatorIndex + 1 ); } //get contents of the helper directory: var dirContents = commonUtils.listDir(path); if(!dirContents){ logger.warn('Could not determine contents for directory "'+path+'"'); return; ////////////////////// EARLY EXIT ////////////////////////////// } else if(! commonUtils.isArray(dirContents) || dirContents.length < 1){ logger.warn('Invalid information for contents of directory "'+path+'": '+dirContents); return; ////////////////////// EARLY EXIT ////////////////////////////// } //check, if there is an implementation file for this helper: var helperIsSpecified = false; for(var i=0, size= dirContents.length; i < size; ++i){ if(dirContents[i] === fileName){ helperIsSpecified = true; break; } } if( ! helperIsSpecified){ if(logger.isVerbose()) logger.v("[HELPER] no helper available (not implemented) at '"+ helperPath+"'"); return; ////////////////////// EARLY EXIT ////////////////////////////// } } //if there is a file: load the helper commonUtils.loadScript(helperPath, function(result){ if(logger.isVerbose()) logger.v("[HELPER] load "+ helperPath);//debug var constr = ctx[name]; //FIXME HACK for handling exported constructor if(typeof result === 'function' && result.name === name){ constr = result; } self.helper = new Helper(self, name, constr); }, function(exception) { // print out an error message logger.error("[WARN] Could not load helper -> '"+ helperPath + "'", exception); //failure } ); }; /** * This function performs an action of a controller - which is represented by this instance of the Controller <br> * class - by calling the method from the corresponding controller, e.g. assets/www/controllers/application.js * * @function perform * @param {String} actionName Name of the method to be executed * @param {Object} data Data to pass to the method of the controller as argument * @returns {Object} The return value of the executed method * @public * @memberOf mmir.ctrl.Controller# */ Controller.prototype.perform = function(actionName, data){ if(logger.isVerbose()) logger.v("should perform '" + actionName + "' of '" + this.name + "'"+ ((typeof data !== 'undefined' && data !== null)? " with data: "+JSON.stringify(data): ""));//debug if(arguments.length > 2){ return this.impl[actionName](data, arguments[2]); } else { return this.impl[actionName](data); } }; /** * * This function performs an action of a controller, but only if an action with this name exists; otherwise nothing is done. * * In difference to perform(..), the method does not trigger an ERROR, if the action does not exist / is not implemented. * As a consequence, this method refers to "optionally" implemented functions, whereas perform(..) refers to mandatory functions. * * @function performIfPresent * @param {String} actionName Name of the method to be executed * @param {Object} data Data to pass to the method of the controller as argument * @returns {Object} The return value of the executed method * @public * @memberOf mmir.ctrl.Controller# */ Controller.prototype.performIfPresent = function(actionName, data){ if(typeof this.impl[actionName] === 'function'){ if(logger.isVerbose()) logger.v("performing '" + actionName + "' of '" + this.name + "'"+ ((typeof data !== 'undefined' && data !== null)? " with data: "+JSON.stringify(data): ""));//debug return this.perform.apply(this, arguments); } else if(typeof this.impl[actionName] !== 'undefined'){ if(logger.isVerbose()) logger.info("could not perform '" + actionName + "' of '" + this.name + "'"+ ((typeof data !== 'undefined' && data !== null)? " with data: "+JSON.stringify(data): "")+": no function ("+typeof this.impl[actionName]+")");//debug } else { if(logger.isVerbose()) logger.debug("could not perform '" + actionName + "' of '" + this.name + "'"+ ((typeof data !== 'undefined' && data !== null)? " with data: "+JSON.stringify(data): "")+": not implemented (undefined)");//debug } }; /** * This function performs a helper action of a controller by calling the appropriate method<br> * {@link mmir.ctrl.Helper#perform} of the instance of the helper class associated with the controller. * * @function performHelper * @param {String} actionName Name of the helper method to be executed * @param {Object} data Data to pass to the helper method as argument * @returns {Object} The return value of the executed method * @public * @memberOf mmir.ctrl.Controller# */ Controller.prototype.performHelper = function(actionName, data){ if(arguments.length > 2){ return this.helper.perform(actionName, data, arguments[2]); } else { return this.helper.perform(actionName, data); } }; /** * Returns the helper of the controller instance. * * @function getHelper * @returns {mmir.ctrl.Helper} The helper instance * @public * @memberOf mmir.ctrl.Controller# */ Controller.prototype.getHelper = function(){ return this.helper; }; /** * Stores all names of the views of the controller by iterating over the array of the views definition.<br> * This function is called by the constructor of the {@link mmir.ctrl.Controller} class. * * @function parseViews * @param {Array} viewDefs Array of the json-definition of the controllers views - containing name of the views and their corresponding path to the js-files * @public * @memberOf mmir.ctrl.Controller# */ Controller.prototype.parseViews = function(viewDefs){ for(var i=0, size = viewDefs.length; i < size; ++i){ this.views.push(viewDefs[i].name); } }; /** * Stores all names of the partials of the controller by iterating over the array of the partials definition.<br> * This function is called by the constructor of the {@link mmir.ctrl.Controller} class. * * @function parsePartials * @param {Array} partialDefs Array of the json-definition of the controllers partials - containing name of the partials and their corresponding path to the js-files * @public * @memberOf mmir.ctrl.Controller# */ Controller.prototype.parsePartials = function(partialDefs){ for(var i=0, size = partialDefs.length; i < size; ++i){ this.partials.push(partialDefs[i].name); } }; /** * Returns the view names for the controller instance. * * @function getViewNames * @returns {Array<String>} An array of the names of the controller's views * @public * @memberOf mmir.ctrl.Controller# */ Controller.prototype.getViewNames = function(){ return this.views; }; /** * Returns the view names for the controller instance. * * TODO should this be private/hidden? -> provides "internal" JSON-details object (used in PresentationManager) * * Each info object has properties: * {String} name * {String} path * * @function getViews * @returns {Array<Object>} An array of the controller's views * @public * @memberOf mmir.ctrl.Controller# */ Controller.prototype.getViews = function(){ return this.def.views; }; /** * Returns the partial names for the controller instance. * * @function getPartialNames * @returns {Array<String>} An array of the names of the controller's partials * @public * @memberOf mmir.ctrl.Controller# */ Controller.prototype.getPartialNames = function(){ return this.partials; }; /** * Returns the partial info object for the controller instance. * * TODO should this be private/hidden? -> provides "internal" JSON-details object (used in PresentationManager) * * Each info object has properties: * {String} name * {String} path * * @function getPartials * @returns {Array<Object>} An array of the controller's partials * @public * @memberOf mmir.ctrl.Controller# */ Controller.prototype.getPartials = function(){ return this.def.partials; }; /** * Returns the layout of the controller instance. * * If undefined, the default layout should be used. * * TODO should this be private/hidden? -> provides "internal" JSON-details object (used in PresentationManager) * * The info object has properties: * {String} name * {String} path * {String} fileName * * @function getLayout * @returns {Object} The controller's layout (may be undefined) * @public * @memberOf mmir.ctrl.Controller# */ Controller.prototype.getLayout = function(){ return this.layout; }; /** * Returns the layout name for the controller instance. * * This is equal to the controller name. * * If undefined, the default layout should be used. * * @function getLayoutName * @returns {String} The controller's layout name (may be undefined) * @public * @memberOf mmir.ctrl.Controller# */ Controller.prototype.getLayoutName = function(){ return this.layout? this.layout.name : this.layout; }; /** * Returns the name of the controller instance. * * @function getName * @returns {String} The name of the controller * @public * @memberOf mmir.ctrl.Controller# */ Controller.prototype.getName = function(){ return this.name; }; return Controller; });