1 /* 2 * Copyright (C) 2012-2013 DFKI GmbH 3 * Deutsches Forschungszentrum fuer Kuenstliche Intelligenz 4 * German Research Center for Artificial Intelligence 5 * http://www.dfki.de 6 * 7 * Permission is hereby granted, free of charge, to any person obtaining a 8 * copy of this software and associated documentation files (the 9 * "Software"), to deal in the Software without restriction, including 10 * without limitation the rights to use, copy, modify, merge, publish, 11 * distribute, sublicense, and/or sell copies of the Software, and to 12 * permit persons to whom the Software is furnished to do so, subject to 13 * the following conditions: 14 * 15 * The above copyright notice and this permission notice shall be included 16 * in all copies or substantial portions of the Software. 17 * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 21 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 */ 26 27 28 define ( ['commonUtils', 'contentElement', 'storageUtils'], 29 //this comment is needed by jsdoc2 [copy of comment for: function Partial(...] 30 /** 31 * The Partial class is a containing the definition of the partial and methods to access the definition. 32 * 33 * @param {Object} ctrl 34 * Controller instance / object 35 * @param {String} name 36 * Name of the Partial 37 * @param {String} definition 38 * Partial description, i.e. the raw template code that will be processed. 39 * May be empty: in this case the processed contents must be 40 * added manually (cf. parser.StorageUtils) 41 * 42 * @requires if param definition is NOT empty: parser.RenderUtils (must be loaded beforehand via <code>require(["renderUtils"]...</code>) 43 * @requires if param definition is NOT empty: parser.ParseUtils (must be loaded beforehand via <code>require(["parseUtils"]...</code>) 44 * 45 * @name Partial 46 * @class 47 */ 48 function ( 49 commonUtils, ContentElement, parser 50 ){ 51 /** @scope Partial.prototype *///for jsdoc2 52 53 //set to @ignore in order to avoid doc-duplication in jsdoc3 54 /** 55 * @ignore 56 * 57 * The Partial class is a containing the definition of the partial and methods to access the definition. 58 * 59 * @constructs Partial 60 * @param {Object} ctrl 61 * Controller instance / object 62 * @param {String} name 63 * Name of the Partial 64 * @param {String} definition 65 * Partial description, i.e. the raw template code that will be processed. 66 * May be empty: in this case the processed contents must be 67 * added manually (cf. parser.StorageUtils) 68 * 69 * @requires if param definition is NOT empty: parser.RenderUtils (must be loaded beforehand via <code>require(["renderUtils"]...</code>) 70 * @requires if param definition is NOT empty: parser.ParseUtils (must be loaded beforehand via <code>require(["parseUtils"]...</code>) 71 * 72 */ 73 function Partial(ctrl, name, definition){ 74 // var HTMLCommentRegExp = /<!--[\s\S]*?-->/g; 75 76 if(definition){ 77 //remove HTML comments: 78 definition = definition.replace(commonUtils.regexHTMLComment, ''); 79 } 80 81 this.controller = ctrl; 82 this.def = definition; 83 this.name = name; 84 // console.log("[Partial] parsed Partial '" +this.controller + "-"+this.name+ "'."); 85 86 if(definition){ 87 88 var contentElementInfo = { 89 //this name is purely informational: 90 name : this.controller.getName() + 'Partial', 91 content : this.def 92 }; 93 this.contentElement = new ContentElement(contentElementInfo, this, require('parseUtils'), require('renderUtils')); 94 } 95 } 96 97 98 /** 99 * Gets the definition of a partial. 100 * 101 * @function 102 * @returns {String} The partial description string 103 */ 104 Partial.prototype.getDefinition = function(){ 105 return this.def; 106 }; 107 108 /** 109 * Gets the name of a partial. 110 * 111 * @function 112 * @returns {String} The name of the partial 113 */ 114 Partial.prototype.getName = function(){ 115 return this.name; 116 }; 117 118 /** 119 * Gets the controller of a partial - each partial is assigned to a specific controller, although they can be used from different controllers. 120 * 121 * @function 122 * @returns {Object} The controller of the partial 123 */ 124 Partial.prototype.getController = function(){ 125 return this.controller; 126 }; 127 128 /** 129 * Gets the {@link mmir.ContentElement}, i.e. the content that this instance represents. 130 * 131 * @function 132 * @returns {mmir.ContentElement} The ContentElement object 133 */ 134 Partial.prototype.getContentElement = function(){ 135 return this.contentElement; 136 }; 137 138 Partial.prototype.stringify = function(){ 139 140 // "plain properties" list 141 var propList = [ 142 'name', 143 'def' 144 ]; 145 146 //Array-properties 147 var stringifyablePropList = [ 148 'contentElement' //element type: ContentElement (stringify-able) 149 ]; 150 151 //function for iterating over the property-list and generating JSON-like entries in the string-buffer 152 var appendStringified = parser.appendStringified; 153 154 var moduleNameString = '"'+this.name+this.getController().getName()+'Partial"'; 155 156 //TODO use requirejs mechanism? (NOTE there may occur timing problems for loading/registering the JS file, and querying the PresentationManager for it ...) 157 // var sb = ['define('+moduleNameString+', ["storageUtils"], function(parser){ return parser.restoreObject({ classConstructor: "partial"', ',']; 158 var sb = ['require("storageUtils").restoreObject({ classConstructor: "partial"', ',']; 159 160 appendStringified(this, propList, sb); 161 162 //non-primitives properties with stringify() function: 163 appendStringified(this, stringifyablePropList, sb, null, function arrayValueExtractor(name, stringifyableValue){ 164 return stringifyableValue.stringify(); 165 }); 166 167 168 //TODO should require() be replaced by define()-dependency declaration? 169 // NOTE the use of require() here, assumes that the dependency has already been loaded (i.e. has already been request by some other module!) 170 sb.push( 'initPublish: function(){ require("presentationManager").addPartial(this.getController(), this); }'); 171 sb.push(','); 172 173 //TODO is there a better way to store the controller? -> by its contoller's name, and add a getter function... 174 if(this['controller']){ 175 176 //getter/setter function for controller 177 // (NOTE: this init-function needs to be called before controller can be accessed!) 178 sb.push( 'initController: function(){'); 179 180 // store controller-name: 181 sb.push( ' var ctrlName = '); 182 sb.push( JSON.stringify(this.getController().getName()) ); 183 184 // ... and the getter/setter code: 185 sb.push( '; this.controller = require("controllerManager").getController(ctrlName); },' );//TODO see remark about use of require() above 186 187 188 //add initializer function 189 // (NOTE: needs to be called before controller or renderer can be accessed!) 190 sb.push( 'init: function(){'); 191 sb.push( ' this.initController(); ' ); 192 sb.push( ' }' ); 193 194 //NOTE: need to add comma in a separate entry 195 // (-> in order to not break the removal method of last comma, see below) 196 sb.push( ',' ); 197 } 198 199 //if last element is a comma, remove it 200 if(sb[sb.length - 1] === ','){ 201 sb.splice( sb.length - 1, 1); 202 } 203 204 //TODO use requirejs mechanism? (see remark above) 205 // sb.push(' }, true); });\n require([' //<- add require-call, so that this JS-file adds itself to the loaded dependencies in requirejs 206 // + moduleNameString + ']);'); 207 208 sb.push(' }, true, '+parser.STORAGE_FILE_FORMAT_NUMBER+');'); 209 return sb.join(''); 210 }; 211 212 return Partial; 213 214 }); 215 216