1 /*global global: true, process: true, require: true */ 2 3 /** 4 * Factory to generate the `GCN' object and expose it to the global context. 5 * In browsers the global context will be the `window' object. In nodejs, it 6 * will be `global'. 7 */ 8 GCN = (function (global) { 9 10 'use strict'; 11 12 // Check whether we are in nodeJS context. 13 if (typeof process !== 'undefined' && process.versions && 14 process.versions.node) { 15 global.isNode = true; 16 17 var XMLHttpRequest = require("xmlhttprequest").XMLHttpRequest; 18 19 // Expose jQuery into the global scope. 20 global.$ = global.jQuery = require('jquery'); 21 22 // Overwrite jQuery's transport. 23 global.jQuery.ajaxSettings.xhr = function () { 24 return new XMLHttpRequest(); 25 }; 26 } 27 28 /** 29 * @private 30 * @type {boolean} A flag to indicate whether or not a handler has been 31 * registerd through the `GCN.onRender()' function. 32 */ 33 var hasOnRenderHandler = false; 34 35 /** 36 * @private 37 * @type {boolean} A flag to indicate whether or not a handler has been 38 * registerd through the `GCN.onError()' function. 39 */ 40 var hasOnErrorHandler = false; 41 42 /** 43 * @type {boolean} An internal flag that stores whether an authentication 44 * handler has been set. 45 */ 46 var hasAuthenticationHandler = false; 47 48 /** 49 * GCN Library error object. This is the object passed to error handlers. 50 * 51 * @class GCNError 52 * @param {string} code 53 * @param {string} message 54 * @param {object} data 55 */ 56 var GCNError = function (code, message, data) { 57 this.code = code; 58 this.message = message; 59 this.data = data; 60 }; 61 62 /** 63 * Returns a human-readable representation of this error object. 64 * 65 * @public 66 * @return {string} 67 */ 68 GCNError.prototype.toString = function () { 69 return 'GCN ERROR (' + this.code + '): "' + (this.message || '') + '"'; 70 }; 71 72 /** 73 * @name GCN 74 * @class 75 * 76 * Base namespace for GCN Library. 77 */ 78 var GCN = global.GCN || {}; 79 80 jQuery.extend(GCN, { 81 /** @lends GCN */ 82 83 /** 84 * @type {object<string, string>} Settings for the gcn library. 85 */ 86 settings: { 87 88 /** 89 * @name settings.lang 90 * @memberOf GCN 91 * @type {string} The language code with which to render tags. 92 */ 93 lang: 'en', 94 95 /** 96 * @const 97 * @name settings.BACKEND_PATH 98 * @memberOf GCN 99 * @type {string} Default GCN backend path. Do not add a trailing 100 * slash here. 101 */ 102 BACKEND_PATH: '/CNPortletapp', 103 104 /** 105 * @const 106 * @name settings.MAGIC_LINK 107 * @memberOf GCN 108 * @type {string} The keyword for the construct that defines Aloha 109 * Editor links. In most Content.Node installations 110 * this will be "gtxalohapagelink", but can be 111 * otherwise defined. 112 */ 113 MAGIC_LINK: 'gtxalohapagelink', 114 115 /** 116 * @const 117 * @name settings.linksRenderMode 118 * @memberOf GCN 119 * @type {string} Determines whether links will be rendered as 120 * back-end urls or front-end urls. Can either be 121 * set to "backend" or "frontend". 122 */ 123 linksRenderMode: 'backend', 124 125 /** 126 * @memberOf GCN 127 * @default false 128 * @type {bool|int|string} Set a channelid to work on for multichannelling 129 * or false if no channel should be used 130 */ 131 channel: false 132 }, 133 134 /** 135 * Publish a message 136 * 137 * @param {string} message channel name 138 * @param {*=} params 139 */ 140 pub: function (channel, params) { 141 if (!hasOnErrorHandler && channel === 'error-encountered') { 142 // throw an error if there is no subscription to 143 // error-encountered. 144 throw params; 145 } 146 147 jQuery(GCN).trigger(channel, params); 148 }, 149 150 /** 151 * Subscribe to a message channel 152 * 153 * @param {string} message channel name 154 * @param {function} handler function - message parameters will be passed 155 */ 156 sub: function (channel, handler) { 157 // register default handlers 158 switch (channel) { 159 case 'error-encountered': 160 hasOnErrorHandler = true; 161 break; 162 case 'content-rendered': 163 hasOnRenderHandler = true; 164 break; 165 case 'authentication-required': 166 hasAuthenticationHandler = true; 167 break; 168 } 169 170 jQuery(GCN).bind(channel, function (event, param1, param2, param3) { 171 handler(param1, param2, param3); 172 }); 173 }, 174 175 /** 176 * Tigger an error message 'error-encountered' 177 * 178 * @param {string} error code 179 * @param {string} error message 180 * @param {object} additional error data 181 */ 182 error: function (code, message, data) { 183 var error = new GCNError(code, message, data); 184 this.pub('error-encountered', error); 185 }, 186 187 /** 188 * Returns an object containing the formal error fields. The object 189 * contains a `toString' method to print any uncaught exceptions nicely. 190 * 191 * @param {string} code 192 * @param {string} message 193 * @param {object} data 194 * @return {GCNError} 195 */ 196 createError: function (code, message, data) { 197 return new GCNError(code, message, data); 198 }, 199 200 /** 201 * Wraps the `jQuery.ajax()' method. 202 * 203 * @public 204 * @param {object} settings 205 * @throws HTTP_ERROR 206 */ 207 ajax: function (settings) { 208 if (settings.json) { 209 settings.data = JSON.stringify(settings.json); 210 delete settings.json; 211 } 212 213 settings.dataType = 'json'; 214 settings.contentType = 'application/json; charset=utf-8'; 215 216 jQuery.ajax(settings); 217 }, 218 219 /** 220 * set links render mode if a parameter is given 221 * retrieve it if not 222 * 223 * @param {string} mode 224 * @return {string} mode 225 */ 226 linksRenderMode: function (mode) { 227 if (mode) { 228 GCN.settings.linksRenderMode = mode; 229 } 230 return GCN.settings.linksRenderMode; 231 }, 232 233 /** 234 * set channel if a parameter is given 235 * retrieve it if not 236 * 237 * if you don't want to work on a channel just 238 * set it to false, which is the default value 239 * 240 * @param {string} channelid to be set 241 * @return {string} current channel 242 */ 243 channel: function (channel) { 244 if (channel || channel === false) { 245 GCN.settings.channel = channel; 246 } 247 return GCN.settings.channel; 248 }, 249 250 /** 251 * @param {string} html Rendered content 252 * @param {function(html)} callback Receives the processed html. 253 */ 254 _handleContentRendered: function (html, callback) { 255 if (hasOnRenderHandler) { 256 GCN.pub('content-rendered', [html, callback]); 257 } else { 258 callback(html); 259 } 260 }, 261 262 /** 263 * Handles the ajax transport error. It will invoke the custom error 264 * handler if one is provided, and propagate the error onto the global 265 * handler if the an error handler does not return `false'. 266 * 267 * @param {object} xhr 268 * @param {string} msg The error message 269 * @param {function} handler Custom error handler. 270 * @throws HTTP_ERROR 271 */ 272 handleHttpError: function (xhr, msg, handler) { 273 var throwException = true; 274 275 if (handler) { 276 throwException = handler(GCN.createError('HTTP_ERROR', msg, 277 xhr)); 278 } 279 280 if (throwException !== 'false') { 281 GCN.error('HTTP_ERROR', msg, xhr); 282 } 283 }, 284 285 /** 286 * Handles error that occur when an ajax request succeeds but the 287 * backend responds with an error. 288 * 289 * @param {object} reponse The REST API response object. 290 * @param {function(GCNError):boolean} handler Custom error handler. 291 */ 292 handleResponseError: function (response, handler) { 293 var info = response.responseInfo; 294 var throwException = true; 295 296 if (handler) { 297 throwException = handler(GCN.createError( 298 info.responseCode, 299 info.responseMessage, 300 response 301 )); 302 } 303 304 if (throwException !== false) { 305 GCN.error(info.responseCode, info.responseMessage, response); 306 } 307 }, 308 309 /** 310 * Tiggers the GCN error event. 311 * 312 * @param {GCNError} error 313 * @param {function(GCNError):boolean} handler Custom error handler. 314 * @return {boolean} Whether or not to the exception was thrown. 315 */ 316 handleError: function (error, handler) { 317 var throwException = true; 318 319 if (handler) { 320 throwException = handler(error); 321 } 322 323 if (throwException !== false) { 324 GCN.error(error.code, error.message, error.data); 325 } 326 327 return throwException; 328 }, 329 330 /** 331 * Check if an authentication handler has been registered. 332 * 333 * @return {boolean} True if an handler for the 334 * 'authentication-required' message has been 335 * registered. 336 */ 337 _hasAuthenticationHandler: function () { 338 return hasAuthenticationHandler; 339 } 340 341 }); 342 343 // Expose the GCN library to the global context. This will be `window' in 344 // most cases. 345 return (global.GCN = GCN); 346 347 }(typeof global !== 'undefined' ? global : this)); 348