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. 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 * @param {string} html Rendered content 252 * @param {Chainback} contentObject The ContentObject which was 253 * rendered. 254 * @param {function(html)} callback Receives the processed html. 255 */ 256 _handleContentRendered: function (html, contentObject, callback) { 257 if (hasOnRenderHandler) { 258 GCN.pub('content-rendered', [html, contentObject, callback]); 259 } else { 260 callback(html); 261 } 262 }, 263 264 /** 265 * Handles the ajax transport error. It will invoke the custom error 266 * handler if one is provided, and propagate the error onto the global 267 * handler if the an error handler does not return `false'. 268 * 269 * @param {object} xhr 270 * @param {string} msg The error message 271 * @param {function} handler Custom error handler. 272 * @throws HTTP_ERROR 273 */ 274 handleHttpError: function (xhr, msg, handler) { 275 var throwException = true; 276 277 if (handler) { 278 throwException = handler(GCN.createError('HTTP_ERROR', msg, 279 xhr)); 280 } 281 282 if (throwException !== 'false') { 283 GCN.error('HTTP_ERROR', msg, xhr); 284 } 285 }, 286 287 /** 288 * Handles error that occur when an ajax request succeeds but the 289 * backend responds with an error. 290 * 291 * @param {object} reponse The REST API response object. 292 * @param {function(GCNError):boolean} handler Custom error handler. 293 */ 294 handleResponseError: function (response, handler) { 295 var info = response.responseInfo; 296 var throwException = true; 297 298 if (handler) { 299 throwException = handler(GCN.createError( 300 info.responseCode, 301 info.responseMessage, 302 response 303 )); 304 } 305 306 if (throwException !== false) { 307 GCN.error(info.responseCode, info.responseMessage, response); 308 } 309 }, 310 311 /** 312 * Tiggers the GCN error event. 313 * 314 * @param {GCNError} error 315 * @param {function(GCNError):boolean} handler Custom error handler. 316 * @return {boolean} Whether or not to the exception was thrown. 317 */ 318 handleError: function (error, handler) { 319 var throwException = true; 320 321 if (handler) { 322 throwException = handler(error); 323 } 324 325 if (throwException !== false) { 326 GCN.error(error.code, error.message, error.data); 327 } 328 329 return throwException; 330 }, 331 332 /** 333 * Check if an authentication handler has been registered. 334 * 335 * @return {boolean} True if an handler for the 336 * 'authentication-required' message has been 337 * registered. 338 */ 339 _hasAuthenticationHandler: function () { 340 return hasAuthenticationHandler; 341 } 342 343 }); 344 345 // Expose the Gentics Content.Node JavaScript API to the global context. 346 // This will be `window' in most cases. 347 return (global.GCN = GCN); 348 349 }(typeof global !== 'undefined' ? global : window)); 350