1 /*global global: true, process: true, require: true, module: true */ 2 3 /** 4 * Establishes the `GCN' object and exposes it in the global context. 5 */ 6 GCN = (function (global) { 7 'use strict'; 8 9 // Check whether we are in nodeJS context. 10 if (typeof process !== 'undefined' && process.versions 11 && process.versions.node) { 12 global.isNode = true; 13 var XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest; 14 jQuery = global.$ = global.jQuery = require('jquery'); 15 global.jQuery.ajaxSettings.xhr = function createNodeXHRForGCN() { 16 return new XMLHttpRequest(); 17 }; 18 // http://stackoverflow.com/a/6432602 19 global.jQuery.support.cors = true; 20 } 21 22 /** 23 * @private 24 * @type {boolean} A flag to indicate whether or not a handler has been 25 * registerd through the `GCN.onRender()' function. 26 */ 27 var hasOnRenderHandler = false; 28 29 /** 30 * @private 31 * @type {boolean} A flag to indicate whether or not a handler has been 32 * registerd through the `GCN.onError()' function. 33 */ 34 var hasOnErrorHandler = false; 35 36 /** 37 * @type {boolean} An internal flag that stores whether an authentication 38 * handler has been set. 39 */ 40 var hasAuthenticationHandler = false; 41 42 /** 43 * GCN JS API error object. This is the object passed to error handlers. 44 * 45 * @class GCNError 46 * @param {string} code 47 * @param {string} message 48 * @param {object} data 49 */ 50 var GCNError = function (code, message, data) { 51 this.code = code; 52 this.message = message; 53 this.data = data; 54 }; 55 56 /** 57 * Returns a human-readable representation of this error object. 58 * 59 * @public 60 * @return {string} 61 */ 62 GCNError.prototype.toString = function () { 63 return 'GCN ERROR (' + this.code + '): "' + (this.message || '') + '"'; 64 }; 65 66 /** 67 * @name GCN 68 * @class 69 * 70 * Base namespace for the Gentics Content.Node JavaScript API. 71 */ 72 var GCN = global.GCN || {}; 73 74 jQuery.extend(GCN, { 75 /** @lends GCN */ 76 77 /** 78 * @type {object} Reference to the global context. 79 */ 80 global: global, 81 82 /** 83 * @type {object<string, string>} Settings for the Gentics Content.Node 84 * JavaScript API. 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 129 * multichannelling or false if no channel 130 * should be used 131 */ 132 channel: false 133 }, 134 135 /** 136 * Publish a message 137 * 138 * @param {string} message channel name 139 * @param {*=} params 140 */ 141 pub: function (channel, params) { 142 if (!hasOnErrorHandler && channel === 'error-encountered') { 143 // throw an error if there is no subscription to 144 // error-encountered. 145 throw params; 146 } 147 148 jQuery(GCN).trigger(channel, params); 149 }, 150 151 /** 152 * Subscribe to a message channel 153 * 154 * @param {string} message channel name 155 * @param {function} handler function - message parameters will be 156 * passed. 157 */ 158 sub: function (channel, handler) { 159 // register default handlers 160 switch (channel) { 161 case 'error-encountered': 162 hasOnErrorHandler = true; 163 break; 164 case 'content-rendered': 165 hasOnRenderHandler = true; 166 break; 167 case 'authentication-required': 168 hasAuthenticationHandler = true; 169 break; 170 } 171 172 jQuery(GCN).bind(channel, function (event, param1, param2, param3) { 173 handler(param1, param2, param3); 174 }); 175 }, 176 177 /** 178 * Tigger an error message 'error-encountered'. 179 * 180 * @param {string} error code 181 * @param {string} error message 182 * @param {object} additional error data 183 */ 184 error: function (code, message, data) { 185 var error = new GCNError(code, message, data); 186 this.pub('error-encountered', error); 187 }, 188 189 /** 190 * Returns an object containing the formal error fields. The object 191 * contains a `toString' method to print any uncaught exceptions 192 * nicely. 193 * 194 * @param {string} code 195 * @param {string} message 196 * @param {object} data 197 * @return {GCNError} 198 */ 199 createError: function (code, message, data) { 200 return new GCNError(code, message, data); 201 }, 202 203 /** 204 * Wraps the `jQuery.ajax()' method. 205 * 206 * @public 207 * @param {object} settings 208 * @throws HTTP_ERROR 209 */ 210 ajax: function (settings) { 211 if (settings.json) { 212 settings.data = JSON.stringify(settings.json); 213 delete settings.json; 214 } 215 settings.dataType = 'json'; 216 settings.contentType = 'application/json; charset=utf-8'; 217 jQuery.ajax(settings); 218 }, 219 220 /** 221 * Set links render mode if a parameter is given 222 * retrieve it if not 223 * 224 * @param {string} mode 225 * @return {string} mode 226 */ 227 linksRenderMode: function (mode) { 228 if (mode) { 229 GCN.settings.linksRenderMode = mode; 230 } 231 return GCN.settings.linksRenderMode; 232 }, 233 234 /** 235 * Set channel if a parameter is given retrieve it otherwise. 236 * 237 * If you don't want to work on a channel just set it to false, which 238 * is the default value. 239 * 240 * @param {string|boolean} channel The id of the channel to be set or false to unset the channel. 241 * @return {string} current channel id. 242 */ 243 channel: function (channel) { 244 if (channel || false === channel) { 245 GCN.settings.channel = channel; 246 } 247 return GCN.settings.channel; 248 }, 249 250 /** 251 * Constructs the nodeId query parameter for rest calls. 252 * 253 * @param {AbstractContentObject} contentObject A content object instance. 254 * @param {string=} delimiter Optional delimiter character. 255 * @return {string} Query parameter string. 256 */ 257 _getChannelParameter: function (contentObject, delimiter) { 258 if (false === contentObject._channel) { 259 return ''; 260 } 261 return (delimiter || '?') + 'nodeId=' + contentObject._channel; 262 }, 263 264 /** 265 * @param {string} html Rendered content 266 * @param {Chainback} contentObject The ContentObject which was 267 * rendered. 268 * @param {function(html)} callback Receives the processed html. 269 */ 270 _handleContentRendered: function (html, contentObject, callback) { 271 if (hasOnRenderHandler) { 272 GCN.pub('content-rendered', [html, contentObject, callback]); 273 } else { 274 callback(html); 275 } 276 }, 277 278 /** 279 * Handles the ajax transport error. It will invoke the custom error 280 * handler if one is provided, and propagate the error onto the global 281 * handler if the an error handler does not return `false'. 282 * 283 * @param {object} xhr 284 * @param {string} msg The error message 285 * @param {function} handler Custom error handler. 286 * @throws HTTP_ERROR 287 */ 288 handleHttpError: function (xhr, msg, handler) { 289 var throwException = true; 290 291 if (handler) { 292 throwException = handler(GCN.createError('HTTP_ERROR', msg, 293 xhr)); 294 } 295 296 if (throwException !== 'false') { 297 GCN.error('HTTP_ERROR', msg, xhr); 298 } 299 }, 300 301 /** 302 * Handles error that occur when an ajax request succeeds but the 303 * backend responds with an error. 304 * 305 * @param {object} reponse The REST API response object. 306 * @param {function(GCNError):boolean} handler Custom error handler. 307 */ 308 handleResponseError: function (response, handler) { 309 var info = response.responseInfo; 310 var throwException = true; 311 312 if (handler) { 313 throwException = handler(GCN.createError( 314 info.responseCode, 315 info.responseMessage, 316 response 317 )); 318 } 319 320 if (throwException !== false) { 321 GCN.error(info.responseCode, info.responseMessage, response); 322 } 323 }, 324 325 /** 326 * Tiggers the GCN error event. 327 * 328 * @param {GCNError} error 329 * @param {function(GCNError):boolean} handler Custom error handler. 330 * @return {boolean} Whether or not to the exception was thrown. 331 */ 332 handleError: function (error, handler) { 333 var throwException = true; 334 335 if (handler) { 336 throwException = handler(error); 337 } 338 339 if (throwException !== false) { 340 GCN.error(error.code, error.message, error.data); 341 } 342 343 return throwException; 344 }, 345 346 /** 347 * Check if an authentication handler has been registered. 348 * 349 * @return {boolean} True if an handler for the 350 * 'authentication-required' message has been 351 * registered. 352 */ 353 _hasAuthenticationHandler: function () { 354 return hasAuthenticationHandler; 355 } 356 357 }); 358 359 // Expose the Gentics Content.Node JavaScript API to the global context. 360 // This will be `window' in most cases. 361 return (global.GCN = GCN); 362 363 }(typeof global !== 'undefined' ? global : window)); 364