Source

meadco-core.js

  1. /**
  2. * Static class for namespace creation and core utility functions for ScriptX.Services client libraries.
  3. *
  4. * This must be included before any other files from this package.
  5. *
  6. * The implementation is for use in a browser only, not general runtime javascript environments.
  7. *
  8. * This code is necessarily 'old-fashioned' as it may find itself running in old versions of IE.
  9. *
  10. * @namespace MeadCo
  11. */
  12. ; (function (name, definition) {
  13. var theModule = definition();
  14. // var scope = (this.jQuery || this.ender || this.$ || this);
  15. // we always go for window
  16. var scope = this;
  17. // hack ...
  18. //
  19. // MeadCo.ScriptX and MeadCo.Licensing may already be defined
  20. // when we run -- they would happily extend this implementation
  21. // and we should extend theirs. This is a horible way to do it.
  22. //
  23. var oldscope = null;
  24. if (typeof scope[name] !== 'undefined') {
  25. // console.log(name + " already exists");
  26. oldscope = scope[name];
  27. }
  28. scope[name] = theModule;
  29. if (oldscope !== null) {
  30. var newscope = scope[name];
  31. // console.log("preserving old scope ... ");
  32. for (var prop in oldscope) {
  33. if (oldscope.hasOwnProperty(prop)) {
  34. // console.log("will preserve: " + prop);
  35. newscope[prop] = oldscope[prop];
  36. }
  37. }
  38. }
  39. // this is moderately poor .. assuming this code is executing
  40. // as the root of the name space, which it is and assumes
  41. // it implements inheritable extendNamespace(), which it does.
  42. // For all that, it means that the root gets to decide where this
  43. // is (i.e. in a common namespace or the global object)
  44. theModule.scope = scope;
  45. })('MeadCo', function () {
  46. // protected API
  47. var outerScope = this;
  48. var version = "1.16.0.0"; // matches the highest version number of sub-classes.
  49. var bLog = ((typeof (MeadCo) !== "undefined" && typeof (MeadCo.logEnable) !== "undefined")) ? MeadCo.logEnable : false;
  50. var bUseFetch = ((typeof (MeadCo) !== "undefined" && typeof (MeadCo.useFetch) !== "undefined")) ? MeadCo.useFetch : false;
  51. var log = function (str) {
  52. if (bLog) {
  53. console.log("MeadCo :: " + str);
  54. }
  55. };
  56. var warn = function (str) {
  57. console.warn("MeadCo :: " + str);
  58. };
  59. var error = function (str) {
  60. console.error("MeadCo :: " + str);
  61. };
  62. // extend the namespace
  63. outerScope.extendMeadCoNamespace = function (name, definition) {
  64. var theModule = definition()
  65. log("MeadCo root extending namespace: " + name);
  66. // walk/build the namespace part by part and assign the module to the leaf
  67. var namespaces = name.split(".");
  68. var scope = (outerScope.scope || this.jQuery || this.ender || this.$ || this);
  69. for (var i = 0; i < namespaces.length; i++) {
  70. var packageName = namespaces[i];
  71. if (i === namespaces.length - 1) {
  72. if (typeof scope[packageName] === "undefined") {
  73. log("installing implementation at: " + packageName);
  74. scope[packageName] = theModule;
  75. } else {
  76. log("Warning - extending package: " + packageName);
  77. var oldscope = scope[packageName];
  78. scope[packageName] = theModule;
  79. var newscope = scope[packageName];
  80. log("preserving old scope ... ");
  81. for (var prop in oldscope) {
  82. if (oldscope.hasOwnProperty(prop)) {
  83. log("will preserve: " + prop);
  84. newscope[prop] = oldscope[prop];
  85. }
  86. }
  87. }
  88. } else if (typeof scope[packageName] === "undefined") {
  89. log("initialising new: " + packageName);
  90. scope[packageName] = {};
  91. } else {
  92. log("using existing package: " + packageName);
  93. }
  94. scope = scope[packageName];
  95. }
  96. };
  97. /*
  98. * Extract the error text from jQuery AJAX response
  99. *
  100. * @param {string} logText The lead-in text for a console.log entry
  101. * @param {object} jqXhr jQuery ajax header
  102. * @param {string} textStatus textStatus result determined by jQuery
  103. * @param {string} errorThrown The server exception dewtermined by jQuery
  104. * @returns {string} The error text to display
  105. */
  106. function parseError(logText, jqXhr, textStatus, errorThrown) {
  107. error("**warning: AJAX call failure in " + logText + ": [" +
  108. textStatus +
  109. "], [" +
  110. errorThrown +
  111. "], [" +
  112. jqXhr.responseText +
  113. "], [" +
  114. jqXhr.statusText +
  115. "]");
  116. if (errorThrown === "" || errorThrown === "Internal Server Error") {
  117. if (textStatus !== "error") {
  118. errorThrown = jqXhr.responseText || textStatus;
  119. }
  120. else {
  121. if (typeof jqXhr.responseJSON === "object" && typeof jqXhr.responseJSON.Message === "string") {
  122. errorThrown = jqXhr.responseJSON.Message;
  123. }
  124. else {
  125. if (typeof jqXhr.responseText === "string") {
  126. errorThrown = jqXhr.responseText;
  127. }
  128. else
  129. errorThrown = "Server or network error";
  130. }
  131. }
  132. }
  133. else {
  134. if (typeof jqXhr.responseJSON !== "object" && typeof jqXhr.responseText === "string" && jqXhr.responseText.length > 0) {
  135. errorThrown = jqXhr.responseText;
  136. }
  137. }
  138. error(" error parsed to --> [" + errorThrown + "]");
  139. return errorThrown;
  140. }
  141. log("MeadCo root namespace " + version + " loaded.");
  142. // public API.
  143. return {
  144. /**
  145. * Sends the content to the console (if informational logging is enabled)
  146. * @function log
  147. * @memberof MeadCo
  148. * @param {string} text to send to console
  149. */
  150. log: log,
  151. /**
  152. * Marks the content as a warning and sends to the console
  153. * @function warn
  154. * @memberof MeadCo
  155. * @param {string} text to send to console
  156. */
  157. warn: warn,
  158. /**
  159. * Marks the content as an error and sends to the console
  160. * @function error
  161. * @memberof MeadCo
  162. * @param {string} text to send to console
  163. */
  164. error: error,
  165. /**
  166. * Get the version of this module as a string major.minor.hotfix.build
  167. * @property {string} version
  168. * @memberof MeadCo
  169. */
  170. get version() { return version; },
  171. /**
  172. * Get/set state of logging to console of informational messages. Default is off
  173. * @property {boolean} logEnabled
  174. * @memberof MeadCo
  175. */
  176. get logEnabled() { return bLog; },
  177. set logEnabled(bEnable) {
  178. bLog = bEnable;
  179. },
  180. /**
  181. * Get/set state of forcing use of fetch even if jQuery(.ajax) is available. Default is off
  182. * @property {boolean} logEnabled
  183. * @memberof MeadCo *
  184. */
  185. get fetchEnabled() { return bUseFetch; },
  186. set fetchEnabled(bEnable) {
  187. bUseFetch = bEnable;
  188. },
  189. /**
  190. * Create a namespace
  191. * @function createNS
  192. * @memberof MeadCo
  193. * @param {string} namespace path of the namespace
  194. * @returns {object} static object for the namespace
  195. * @example
  196. * var ui = MeadCo.createNS("MeadCo.ScriptX.Print.UI");
  197. * ui.Show = function() { alert("hello"); }
  198. */
  199. createNS: function (namespace) {
  200. var nsparts = namespace.split(".");
  201. var parent = outerScope.scope.MeadCo;
  202. // we want to be able to include or exclude the root namespace so we strip
  203. // it if it's in the namespace
  204. if (nsparts[0] === "MeadCo") {
  205. nsparts = nsparts.slice(1);
  206. }
  207. // loop through the parts and create a nested namespace if necessary
  208. for (var i = 0; i < nsparts.length; i++) {
  209. var partname = nsparts[i];
  210. // check if the current parent already has the namespace declared
  211. // if it isn't, then create it
  212. if (typeof parent[partname] === "undefined") {
  213. parent[partname] = {};
  214. }
  215. // get a reference to the deepest element in the hierarchy so far
  216. parent = parent[partname];
  217. }
  218. // the parent is now constructed with empty namespaces and can be used.
  219. // we return the outermost namespace
  220. return parent;
  221. },
  222. /**
  223. * @private
  224. * @param {object} s the scope in which to create namesapces
  225. */
  226. set scope(s) { outerScope.scope = s; },
  227. /**
  228. * Get the url to a ScriptX.Services api. If an api is already present, it is replaced.
  229. *
  230. * @function makeApiEndPoint
  231. * @memberof MeadCo
  232. * @param {string} serverUrl url to the server
  233. * @param {string} apiLocation the api, e.g. v1/printhtml
  234. * @returns {string} url to the api
  235. */
  236. makeApiEndPoint: function (serverUrl, apiLocation) {
  237. // check if given partial ...
  238. var p = serverUrl.indexOf("/api");
  239. if (p === -1) {
  240. if (serverUrl.lastIndexOf("/") !== (serverUrl.length - 1)) {
  241. serverUrl += "/";
  242. }
  243. serverUrl += "api/" + apiLocation;
  244. }
  245. else {
  246. // given another api, chop and replace with requested api
  247. serverUrl = serverUrl.substring(0, p) + "/api/" + apiLocation;
  248. }
  249. return serverUrl;
  250. },
  251. /**
  252. * Get the url to a ScriptX.Services service endpoint.
  253. *
  254. * @function makeServiceEndPoint
  255. * @memberof MeadCo
  256. * @param {string} serverUrl url to the server
  257. * @param {string} endPoint the service endpoint, e.g. v1/preview
  258. * @returns {string} url to the endpoint
  259. */
  260. makeServiceEndPoint: function (serverUrl, endPoint) {
  261. // check if given partial ...
  262. var p = serverUrl.indexOf("/api");
  263. if (p === -1) {
  264. if (serverUrl.lastIndexOf("/") !== (serverUrl.length - 1)) {
  265. serverUrl += "/";
  266. }
  267. serverUrl += endPoint;
  268. }
  269. else {
  270. // given another api, chop and replace with requested api
  271. serverUrl = serverUrl.substring(0, p) + "/" + endPoint;
  272. }
  273. return serverUrl;
  274. },
  275. /**
  276. * Extract the error text from jQuery AJAX response
  277. *
  278. * @function parseAjaxError
  279. * @memberof MeadCo
  280. *
  281. * @param {string} logText The lead-in text for a console.log entry
  282. * @param {object} jqXhr jQuery ajax header
  283. * @param {string} textStatus textStatus result determined by jQuery
  284. * @param {string} errorThrown The server exception dewtermined by jQuery
  285. * @returns {string} The error text to display
  286. */
  287. parseAjaxError: function (logText, jqXhr, textStatus, errorThrown) {
  288. return parseError(logText, jqXhr, textStatus, errorThrown);
  289. },
  290. /**
  291. * Extract the error text from browser fetch response
  292. *
  293. * @function parseFetchError
  294. * @memberof MeadCo
  295. *
  296. * @param {object} errorThrown error caught from fetch
  297. * @returns {string} The error text to display
  298. */
  299. parseFetchError: function (logText, errorThrown) {
  300. const msg = typeof errorThrown === "string" ? errorThrown : errorThrown.message;
  301. error("**warning: FETCH call failure in " + logText + ": " + msg);
  302. return msg;
  303. }
  304. };
  305. });