/PhoneGapDemoClient/apps/PhoneGapDemoClient/iphone/native/www/default/wlclient/js/worklight.js

https://bitbucket.org/sebsto/phonegapdemo · JavaScript · 2333 lines · 1739 code · 248 blank · 346 comment · 377 complexity · 1a807f3715c8993de33941517c20ca40 MD5 · raw file

Large files are truncated click here to view the full file

  1. /* JavaScript content from wlclient/js/worklight.js in Common Resources */
  2. /*
  3. * Licensed Materials - Property of IBM
  4. * 5725-G92 (C) Copyright IBM Corp. 2006, 2012. All Rights Reserved.
  5. * US Government Users Restricted Rights - Use, duplication or
  6. * disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
  7. */
  8. /* Copyright (C) Worklight Ltd. 2006-2012. All rights reserved. */
  9. /**
  10. * @requires prototype.js
  11. * @requires busy.js
  12. * @requires dialog.js
  13. */
  14. WL.AppProperty = {
  15. AIR_ICON_16x16_PATH : "AIR_ICON_16x16_PATH",
  16. AIR_ICON_128x128_PATH : "AIR_ICON_128x128_PATH",
  17. DOWNLOAD_APP_LINK : "DOWNLOAD_APP_LINK",
  18. ENVIRONMENT : "ENVIRONMENT",
  19. APP_DISPLAY_NAME : "APP_DISPLAY_NAME",
  20. APP_LOGIN_TYPE : "APP_LOGIN_TYPE",
  21. APP_VERSION : "APP_VERSION",
  22. HEIGHT : "HEIGHT",
  23. IID : "IID",
  24. LATEST_VERSION : "LATEST_VERSION",
  25. LOGIN_DISPLAY_TYPE : "LOGIN_DISPLAY_TYPE",
  26. LOGIN_REALM : "LOGIN_REALM",
  27. LOGIN_POPUP_HEIGHT : "LOGIN_POPUP_HEIGHT",
  28. LOGIN_POPUP_WIDTH : "LOGIN_POPUP_WIDTH",
  29. MAIN_FILE_PATH : "MAIN_FILE_PATH",
  30. SHOW_IN_TASKBAR : "SHOW_IN_TASKBAR",
  31. THUMBNAIL_IMAGE_URL : "THUMBNAIL_IMAGE_URL",
  32. VISTA_DOCK_IMAGE_PATH : "VISTA_DOCK_IMAGE_PATH",
  33. VISTA_DOCK_IMAGE_HEIGHT : "VISTA_DOCK_IMAGE_HEIGHT",
  34. VISTA_DOCK_IMAGE_WIDTH : "VISTA_DOCK_IMAGE_WIDTH",
  35. WELCOME_PAGE_URL : "WELCOME_PAGE_URL",
  36. WIDTH : "WIDTH",
  37. WORKLIGHT_ROOT_URL : "WORKLIGHT_ROOT_URL",
  38. APP_SERVICES_URL : "APP_SERVICES_URL",
  39. WLCLIENT_TIMEOUT_IN_MILLIS : "WLCLIENT_TIMEOUT_IN_MILLIS"
  40. };
  41. // Short alias:
  42. WL.AppProp = WL.AppProperty;
  43. // A copy of the Java GadgetEnvironment version.
  44. var __WLEnvironment = {
  45. PREVIEW : "preview",
  46. IGOOGLE : "igoogle",
  47. VISTA_SIDEBAR : "vista",
  48. OSX_DASHBOARD : "dashboard",
  49. IPHONE : "iphone",
  50. IPAD : "ipad",
  51. EMBEDDED : "embedded",
  52. FACEBOOK : "facebook",
  53. ADOBE_AIR : "air",
  54. ANDROID : "android",
  55. BLACKBERRY : "blackberry",
  56. WINDOWS_PHONE : "windowsphone",
  57. MOBILE_WEB : "mobilewebapp"
  58. };
  59. __WL.prototype.Environment = __WLEnvironment;
  60. WL.Environment = __WLEnvironment;
  61. // Short alias:
  62. WL.Env = WL.Environment;
  63. // Constants for language manipulations
  64. var WL_CLASS_NAME_TRANSLATE = 'translate';
  65. var WL_I18N_MESSAGES = null;
  66. // A copy of the Java AppLoginType version.
  67. WL.AppLoginType = {
  68. LOGIN_ON_STARTUP : "onStartup",
  69. LOGIN_ON_DEMAND : "onDemand",
  70. NO_LOGIN : "never"
  71. };
  72. WL.LoginDisplayType = {
  73. EMBEDDED : "embedded",
  74. POPUP : "popup"
  75. };
  76. WL.UserInfo = {
  77. IS_USER_AUTHENTICATED : "isUserAuthenticated",
  78. USER_NAME : "userName",
  79. LOGIN_NAME : "loginName"
  80. };
  81. WL.Orientation = {
  82. AUTO : -1,
  83. LANDSCAPE : 0,
  84. PORTRAIT : 1
  85. };
  86. WL.FixedViewType = {
  87. TOP : "top",
  88. BOTTOM : "bottom"
  89. };
  90. // In case of shell app load inner app, set it to true to prevent direct update.
  91. WL._isInnerAppChanged = false;
  92. /*
  93. * NOTICE: All server errors MUST be defined with same values in the ErrorCode
  94. * java enumeration.
  95. */
  96. var __WLErrorCode = {
  97. UNEXPECTED_ERROR : "UNEXPECTED_ERROR",
  98. API_INVOCATION_FAILURE : "API_INVOCATION_FAILURE",
  99. USER_INSTANCE_ACCESS_VIOLATION : "USER_INSTANCE_ACCESS_VIOLATION",
  100. AUTHENTICATION_REQUIRED : "AUTHENTICATION_REQUIRED",
  101. DOMAIN_ACCESS_FORBIDDEN : "DOMAIN_ACCESS_FORBIDDEN",
  102. // Client Side Errors
  103. UNRESPONSIVE_HOST : "UNRESPONSIVE_HOST",
  104. LOGIN_FAILURE : "LOGIN_FAILURE",
  105. REQUEST_TIMEOUT : "REQUEST_TIMEOUT",
  106. PROCEDURE_ERROR : "PROCEDURE_ERROR",
  107. UNSUPPORTED_VERSION : "UNSUPPORTED_VERSION",
  108. UNSUPPORTED_BROWSER : "UNSUPPORTED_BROWSER",
  109. DISABLED_COOKIES : "DISABLED_COOKIES"
  110. };
  111. __WL.prototype.ErrorCode = __WLErrorCode;
  112. WL.ErrorCode = __WLErrorCode;
  113. WL.FBRealmPopupOptions = {
  114. width : 1000,
  115. height : 600
  116. };
  117. // save the base url since the WL.StaticAppProps.WORKLIGHT_ROOT_URL &&
  118. // WL.StaticAppProps.APP_SERVICES_URL
  119. WL.StaticAppProps.POSTFIX_WORKLIGHT_ROOT_URL = WL.StaticAppProps.WORKLIGHT_ROOT_URL;
  120. WL.StaticAppProps.POSTFIX_APP_SERVICES_URL = WL.StaticAppProps.APP_SERVICES_URL;
  121. /*
  122. * Worklight Utils
  123. */
  124. __WLUtils = function() {
  125. // ........................Private methods........................
  126. function getStyle(element, cssprop) {
  127. if (element.currentStyle) { // IE
  128. return element.currentStyle[cssprop];
  129. } else if (document.defaultView && document.defaultView.getComputedStyle) { // Firefox
  130. return document.defaultView.getComputedStyle(element, "")[cssprop];
  131. } else { // try and get inline style
  132. return element.style[cssprop];
  133. }
  134. }
  135. function getUrlParam(name) {
  136. name = name.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]");
  137. var regexS = "[\\?&]" + name + "=([^&#]*)";
  138. var regex = new RegExp(regexS);
  139. var results = regex.exec(window.location.href);
  140. if (results == null) {
  141. return "";
  142. } else {
  143. return results[1];
  144. }
  145. }
  146. function getWidth(element) {
  147. var maxWidth = getStyle(element, 'width');
  148. var isPercentage = (maxWidth + '').indexOf('%') > -1;
  149. maxWidth = parseInt(maxWidth, 10);
  150. if (maxWidth === null || isNaN(maxWidth) || maxWidth === 0 || isPercentage) {
  151. maxWidth = getStyle(element, 'maxWidth');
  152. isPercentage = (maxWidth + '').indexOf('%') > -1;
  153. maxWidth = parseInt(maxWidth, 10);
  154. if (maxWidth === null || isNaN(maxWidth) || maxWidth === 0 || isPercentage) {
  155. maxWidth = WLJSX.width(element);
  156. maxWidth = parseInt(maxWidth, 10);
  157. if (maxWidth === null || isNaN(maxWidth)) {
  158. maxWidth = 0;
  159. }
  160. }
  161. }
  162. return maxWidth;
  163. }
  164. // @Deprecated
  165. function doEllipsis(elm, options) {
  166. var currentOptions = {
  167. maxWidth : 0,
  168. addTitle : false
  169. };
  170. WLJSX.Object.extend(currentOptions, options || {});
  171. var origText = elm.innerHTML;
  172. var display = elm.style.display;
  173. elm.style.display = 'inline';
  174. var whiteSpace = elm.style.whiteSpace;
  175. elm.style.whiteSpace = 'nowrap';
  176. var maxWidth = currentOptions.maxWidth > 0 ? currentOptions.maxWidth : getWidth(elm);
  177. var width = elm.style.width;
  178. elm.style.width = 'auto';
  179. // Can't get the width of the element, no ellipsis is performed.
  180. if (maxWidth === 0 || WLJSX.width(elm) <= maxWidth) {
  181. elm.style.display = display;
  182. elm.style.width = width;
  183. elm.style.whiteSpace = whiteSpace;
  184. return;
  185. }
  186. // Reset content of element
  187. var text = origText;
  188. // Start width - assume min 3px per char
  189. var maxNumberOfChars = Math.ceil(maxWidth / 3);
  190. text = text.substring(0, maxNumberOfChars);
  191. // First reduce text size to fit the element
  192. while (WLJSX.width(elm) >= maxWidth && text.length > 3) {
  193. text = text.substr(0, text.length - 2);
  194. WLJSX.html(elm, text);
  195. }
  196. do {
  197. text = text.substr(0, text.length - 1);
  198. WLJSX.html(elm, text + "...");
  199. } while (WLJSX.width(elm) > maxWidth && text.length > 3);
  200. if (text !== origText && currentOptions.addTitle) {
  201. elm.title = origText;
  202. }
  203. elm.style.display = display;
  204. elm.style.width = width;
  205. elm.style.whiteSpace = whiteSpace;
  206. }
  207. this.wlReachableCallback = function(connection) {
  208. };
  209. // .................... Public methods ...........................
  210. this.__networkCheckTimeout = function() {
  211. if (!window.connectivityCheckDone) {
  212. WL.Logger.debug("Connectivity check has timed out");
  213. window.connectivityCheckDone = true;
  214. WL.Utils.dispatchWLEvent(__WL.InternalEvents.REACHABILITY_TEST_FAILURE);
  215. }
  216. };
  217. // checks that the WL server is available, and fires an appropriate event.
  218. this.wlCheckReachability = function() {
  219. this.wlCheckServerReachability();
  220. };
  221. this.wlCheckServerReachability = function() {
  222. var isCheckDone = false;
  223. // iOS's isReachable does not check a server's availability. Rather, it
  224. // merely checks is a socket can be opened.
  225. if (typeof navigator.network != "undefined" && navigator.network.connection.type == 'NONE') {
  226. WL.Utils.dispatchWLEvent(__WL.InternalEvents.REACHABILITY_TEST_FAILURE);
  227. isCheckDone = true;
  228. }
  229. var reachabilityUrl = WL.Client.getAppProperty(WL.AppProp.APP_SERVICES_URL) + "reach";
  230. var xhr = new XMLHttpRequest();
  231. xhr.open("GET", reachabilityUrl, true);
  232. xhr.onreadystatechange = function() {
  233. if (xhr.readyState == 4 && xhr.status == 200) {
  234. clearTimeout(xhrTimeout);
  235. WL.Utils.dispatchWLEvent(__WL.InternalEvents.REACHABILITY_TEST_SUCCESS);
  236. }
  237. };
  238. xhr.send("");
  239. var xhrTimeout = setTimeout(function() {
  240. if (!isCheckDone) {
  241. xhr.abort();
  242. WL.Utils.dispatchWLEvent(__WL.InternalEvents.REACHABILITY_TEST_FAILURE);
  243. }
  244. }, 6000);
  245. };
  246. /**
  247. * Retrieves from the server the suitable skinLoader.js content, based on
  248. * the appId and appVersion parameters, computes the skin name, and pass it
  249. * to the provided callback. The method works only with development server
  250. * (not production).
  251. */
  252. this.__getSkinFromRemoteSkinLoader = function(appId, appVersion, callback) {
  253. // displaying an error message if appId or appVersion are missing
  254. if (!appId) {
  255. WL.SimpleDialog.show(WL.ClientMessages.error, WL.ClientMessages.downloadAppWebResourcesPleaseSpecifyAppID,
  256. [ {
  257. text : WL.ClientMessages.close
  258. } ]);
  259. return;
  260. } else if (!appVersion) {
  261. WL.SimpleDialog.show(WL.ClientMessages.error,
  262. WL.ClientMessages.downloadAppWebResourcesPleaseSpecifyAppVersion, [ {
  263. text : WL.ClientMessages.close
  264. } ]);
  265. return;
  266. }
  267. // send request to the server for getting the app's skinLoader.js
  268. // content
  269. var url = WL.StaticAppProps.WORKLIGHT_BASE_URL + "/dev/appdata?appId=" + appId + "&appVer=" + appVersion
  270. + "&appEnv=" + WL.Client.getEnvironment();
  271. new WLJSX.Ajax.Request(url, {
  272. onSuccess : function(response) {
  273. // evaluating skinLoader.js content (which defines the
  274. // method
  275. // getSkinName), and then passing the callback the
  276. // getSkinName()
  277. // return value
  278. WL._isInnerAppChanged = true;
  279. eval(response.responseJSON.skinLoaderContent);
  280. var newSkinName = getSkinName();
  281. if (response.responseJSON.availableSkins.indexOf(newSkinName) != -1) {
  282. callback(newSkinName);
  283. } else {
  284. WL.SimpleDialog.show(WL.ClientMessages.error, WL.Utils.formatString(
  285. WL.ClientMessages.downloadAppWebResourcesSkinIsNotValid, newSkinName), [ {
  286. text : WL.ClientMessages.close
  287. } ]);
  288. }
  289. },
  290. onFailure : function(response) {
  291. if (response.status == 0) {
  292. WL.SimpleDialog.show(WL.ClientMessages.error,
  293. WL.ClientMessages.downloadAppWebResourcesConnectionToServerUnavailable, [ {
  294. text : WL.ClientMessages.close
  295. } ]);
  296. } else {
  297. switch (response.responseJSON.error) {
  298. case "singleSkin":
  299. WL._isInnerAppChanged = true;
  300. // this is not a real failure, it happens
  301. // whenever the
  302. // target app has only a single skin (and
  303. // therefore it
  304. // has no skinLoader.js file).
  305. callback("default");
  306. break;
  307. case "appNotExist":
  308. WL.SimpleDialog.show(WL.ClientMessages.error, WL.Utils.formatString(
  309. WL.ClientMessages.downloadAppWebResourcesAppIdNotExist, appId), [ {
  310. text : WL.ClientMessages.close
  311. } ]);
  312. break;
  313. case "versionNotExist":
  314. WL.SimpleDialog.show(WL.ClientMessages.error, WL.Utils.formatString(
  315. WL.ClientMessages.downloadAppWebResourcesAppVersionNotExist, appId, appVersion,
  316. WL.Client.getEnvironment()), [ {
  317. text : WL.ClientMessages.close
  318. } ]);
  319. break;
  320. default:
  321. WL.SimpleDialog.show(WL.ClientMessages.error, response.responseJSON.errorText, [ {
  322. text : WL.ClientMessages.close
  323. } ]);
  324. }
  325. }
  326. }
  327. });
  328. };
  329. /**
  330. * @param {Object}
  331. * value
  332. * @return value if defined or null otherwise.
  333. */
  334. this.safeGetValue = function(value) {
  335. if (!WLJSX.Object.isUndefined(value)) {
  336. return value;
  337. } else {
  338. return null;
  339. }
  340. };
  341. /**
  342. * @deprecated - use WL.App.getErrorMessage(
  343. */
  344. this.getErrorMessage = function(e) {
  345. if (e === null) {
  346. return null;
  347. } else if (WLJSX.Object.isString(e)) {
  348. return e;
  349. } else if (e.description) {
  350. return e.description;
  351. } else if (e.message) {
  352. return e.message;
  353. } else if (WLJSX.Object.isArray(e)) {
  354. return e.join(",");
  355. } else {
  356. return e.toString();
  357. }
  358. };
  359. /**
  360. * Adds a parameter to the given URL.
  361. *
  362. * @param {string}
  363. * url
  364. * @param {string}
  365. * parameter name
  366. * @param {string}
  367. * parameter value
  368. * @return the url with the added parameter.
  369. */
  370. this.addParameterToURL = function(url, name, value) {
  371. if (url.indexOf("?") === -1) {
  372. url += "?";
  373. } else {
  374. url += "&";
  375. }
  376. url += (name + '=' + encodeURIComponent(value));
  377. return url;
  378. };
  379. // @Deprecated
  380. this.ellipsisByClassName = function(className, options) {
  381. var elements = WLJSX.$$('.' + className);
  382. for ( var i = 0; i < elements.length; i++) {
  383. doEllipsis(elements[i], options);
  384. }
  385. };
  386. // @Deprecated
  387. this.ellipsisByElement = function(e, options) {
  388. doEllipsis(e, options);
  389. };
  390. this.formatString = function() {
  391. var resStr = arguments[0];
  392. for ( var i = 1; i < arguments.length; i++) {
  393. var re = new RegExp("\\{" + (i - 1) + "\\}", "g");
  394. resStr = resStr.replace(re, arguments[i]);
  395. }
  396. return resStr;
  397. };
  398. this.clearText = function(className, attribute) {
  399. var elementsToClear = WLJSX.$$('.' + className);
  400. var element;
  401. for ( var i = 0; i < elementsToClear.length; i++) {
  402. element = elementsToClear[i];
  403. if (!attribute || attribute === 'innerHTML') {
  404. if (element.tagName.toLowerCase() === 'input') {
  405. element.value = '';
  406. } else {
  407. WLJSX.empty(element);
  408. }
  409. } else if (attribute === 'title') {
  410. element.title = '';
  411. } else if (attribute === 'alt') {
  412. element.alt = '';
  413. }
  414. }
  415. };
  416. this.replaceElementsText = function(parentId, dictionary, attribute) {
  417. if (!dictionary) {
  418. dictionary = WL_I18N_MESSAGES;
  419. }
  420. var cssSelector;
  421. if (parentId) {
  422. cssSelector = "#" + parentId + " ." + WL_CLASS_NAME_TRANSLATE;
  423. } else {
  424. cssSelector = "." + WL_CLASS_NAME_TRANSLATE;
  425. }
  426. var elementsToFill = WLJSX.$$(cssSelector);
  427. var element;
  428. for ( var i = 0; i < elementsToFill.length; i++) {
  429. element = elementsToFill[i];
  430. if (!attribute || attribute === 'innerHTML') {
  431. // Use value instead of innerHTML in input elements
  432. if (element.tagName.toLowerCase() === 'input') {
  433. element.value = dictionary[element.id];
  434. } else {
  435. WLJSX.html(element, dictionary[element.id]);
  436. }
  437. } else if (attribute === 'title') {
  438. element.title = dictionary[element.id];
  439. } else if (attribute === 'alt') {
  440. element.alt = dictionary[element.id];
  441. }
  442. }
  443. };
  444. /*
  445. * Adds the URL prefix to the URL if not already added and
  446. * WL.StaticAppProps.WORKLIGHT_ROOT_URL is set This is used when working
  447. * with desktop gadget and we need a static URL
  448. */
  449. this.createAPIRequestURL = function(path) {
  450. var resultURL;
  451. // if "path" is an absolute URL we just use it
  452. if (path.match('http://') || path.match('https://') || path.match("itms://")) {
  453. resultURL = path;
  454. } else if (path.indexOf("/") === 0) {
  455. // In case using absolute url like "/random" it must be under
  456. // app/services
  457. var appServicesUrl = WL.Client.getAppProperty(WL.AppProp.APP_SERVICES_URL);
  458. resultURL = appServicesUrl.substr(0, appServicesUrl.length - 1) + path;
  459. } else {
  460. // Relative URL
  461. // We take http://<IP>:<PORT>/<app-name>/<env-name>/" - and append
  462. // "path" to it
  463. resultURL = WL.Client.getAppProperty(WL.AppProp.WORKLIGHT_ROOT_URL) + path;
  464. }
  465. return resultURL;
  466. };
  467. /*
  468. * Extends the target object with the source object only with fields and
  469. * methods that do not already exist on the target.
  470. */
  471. this.extend = function(target, source) {
  472. target = WLJSX.Object.extend(WLJSX.Object.clone(source), target);
  473. return target;
  474. };
  475. /*
  476. * extracts the host part of a url. For example, for the input
  477. * url="https://212.10.0.15:8888/application/service/?arg=blue", the result
  478. * would be "212.10.0.15".
  479. */
  480. this.getHostname = function(url) {
  481. var re = new RegExp('^(?:f|ht)tp(?:s)?\://([^/:]+)', 'im');
  482. return url.match(re)[1].toString();
  483. };
  484. this.dispatchWLEvent = function(eventName) {
  485. // ie (WP7/VISTA) support custom event
  486. if (typeof document.createEvent == "undefined") {
  487. WLJSX.trigger(document, eventName);
  488. } else {
  489. var e = document.createEvent('Events');
  490. e.initEvent(eventName, false, false);
  491. document.dispatchEvent(e);
  492. }
  493. };
  494. this.getCurrentSkinName = function() {
  495. var skinName = null;
  496. // readUserPref is syncronized on Android but async on iOS, this is why
  497. // the implementation differ
  498. if (WL.Client.getEnvironment() === WL.Env.ANDROID) {
  499. skinName = WL.App.readUserPref('wlSkinName');
  500. } else if (WL.EnvProfile.isEnabled(WL.EPField.ISIOS)) {
  501. skinName = WL.StaticAppProps.SKIN_NAME;
  502. } else if (WL.Client.getEnvironment() === WL.Env.WINDOWS_PHONE) {
  503. skinName = getUrlParam("skinName");
  504. if (skinName.length == 0) {
  505. skinName = "default";
  506. }
  507. }
  508. // environements that don't support skins should return 'default'
  509. else {
  510. skinName = 'default';
  511. }
  512. return skinName;
  513. };
  514. /**
  515. * function: getFreeSpaceOnDevice return: free space on device in Bytes
  516. * Should be called only for environments that support direct update
  517. * (currently Android + iOS)
  518. */
  519. this.getFreeSpaceOnDevice = function() {
  520. var freeSpace;
  521. if (WL.Client.getEnvironment() === WL.Env.ANDROID) {
  522. freeSpace = cordova.exec(null, null, 'Utils', 'getAvailableSpace', []);
  523. } else if (WL.EnvProfile.isEnabled(WL.EPField.ISIOS)) {
  524. freeSpace = WL.StaticAppProps.FREE_SPACE;
  525. }
  526. // environements that don't support skins should return 'default'
  527. else {
  528. var msg = "WL.Utils.getFreeSpaceOnDevice(..) should be supported only on environments that support direct update";
  529. var ex = new Error(msg);
  530. WL.Logger.error(msg, ex);
  531. throw ex;
  532. }
  533. return Number(freeSpace).toFixed(2);
  534. };
  535. // hide application with a black div
  536. this.addBlackDiv = function() {
  537. var blackDiv = WLJSX.newElement('<div/>', {
  538. 'id' : 'blockingDiv',
  539. 'style' : 'background-color:black; z-index: 9999; position: fix; top:0; left:0; right:0; bottom:0;'
  540. });
  541. document.body.appendChild(blackDiv);
  542. };
  543. this.removeBlackDiv = function() {
  544. while (WLJSX.$('blockingDiv')) {
  545. document.body.removeChild(WLJSX.$('blockingDiv'));
  546. }
  547. };
  548. this.getSkinLoaderChecksum = function() {
  549. var skinLoaderChecksum;
  550. // readUserPref is syncronized on Android but async on iOS, this is why
  551. // the implementation differ
  552. if (WL.Client.getEnvironment() === WL.Env.ANDROID) {
  553. skinLoaderChecksum = WL.App.readUserPref('wlSkinLoaderChecksum');
  554. } else if (WL.EnvProfile.isEnabled(WL.EPField.ISIOS)) {
  555. skinLoaderChecksum = WL.StaticAppProps.SKIN_LOADER_CHECKSUM;
  556. }
  557. // environments that don't support skins should return null
  558. else {
  559. var msg = "WL.Utils.getSkinLoaderChecksum(..) should be supported only on environments that support direct update";
  560. var ex = new Error(msg);
  561. WL.Logger.error(msg, ex);
  562. throw ex;
  563. }
  564. if ((typeof skinLoaderChecksum === 'undefined') || (skinLoaderChecksum == null)
  565. || (skinLoaderChecksum.length == 0)) {
  566. skinLoaderChecksum = WL_SKINLOADER_CHECKSUM.checksum;
  567. WL.Utils.setSkinLoaderChecksum(skinLoaderChecksum);
  568. }
  569. return skinLoaderChecksum;
  570. };
  571. this.setSkinLoaderChecksum = function(skinLoaderChecksum) {
  572. if ((WL.Client.getEnvironment() === WL.Env.ANDROID) || (WL.EnvProfile.isEnabled(WL.EPField.ISIOS))) {
  573. WL.App.writeUserPref('wlSkinLoaderChecksum', skinLoaderChecksum);
  574. }
  575. // environments that don't support skins should return null
  576. else {
  577. var msg = "WL.Utils.setSkinLoaderChecksum(..) should be supported only on environments that support direct update";
  578. var ex = new Error(msg);
  579. WL.Logger.error(msg, ex);
  580. throw ex;
  581. }
  582. };
  583. this.safeInnerHTML = function(target, contentToSet, options) {
  584. // iPhone sometimes just fails to set innerHTML - no idea why. you
  585. // end up with an empty div.
  586. // it's more reliable with a setTimeout but still not reliable enough.
  587. // this function sets the text and then checks it. if it's not
  588. // there, it tries once more. horrible, but necessary.
  589. // note: this really became an issue within the app and was even
  590. // worse in 1st gen and 3g. 3GS was mostly fixed with one timeout,
  591. // whereas even 3 didn't seem to always fix pre-3GS
  592. // some blog posts indicated that they noticed the problem only
  593. // when the messed with location.href
  594. // (http://blog.johnmckerrell.com/2007/03/07/problems-with-safari-and-innerhtml/)
  595. // so i've removed this stuff in the app and location.href is no
  596. // longer changed. seems to be worse with database than it was
  597. // with XHR but assume we'll leave it in place to be safe
  598. var _options = {
  599. onSuccess : function() {
  600. },
  601. onFailure : function() {
  602. WL.Logger.debug("safeInnerHtml error. Could not perform " + target.id + ".innerHtml = " + contentToSet)
  603. .bind(this);
  604. },
  605. count : 10
  606. };
  607. if (!WLJSX.Object.isUndefined(options)) {
  608. _options = WLJSX.Object.extend(_options, options);
  609. }
  610. if (!WL.EnvProfile.isEnabled(WL.EPField.ISIOS)) {
  611. target.innerHTML = contentToSet;
  612. _options.onSuccess();
  613. return;
  614. }
  615. target.innerHTML = contentToSet;
  616. var timeout = 50;
  617. var count = _options.count;
  618. if ((contentToSet != '' && target.innerHTML == '') || (contentToSet == '' && target.innerHTML != '')) {
  619. if (_options.count <= 0) {
  620. _options.onFailure();
  621. } else {
  622. WL.Logger.debug(target.id + ".innerHTML failed. number of attempts remaining: " + count + " ( + "
  623. + timeout + "ms timout)");
  624. --count;
  625. _options.count = count;
  626. setTimeout(function() {
  627. safeInnerHTML(target, contentToSet, _options);
  628. }, timeout);
  629. }
  630. } else {
  631. _options.onSuccess();
  632. }
  633. };
  634. /**
  635. * Helper function, there is a difference between IOS and Android In Android
  636. * Cordova returns the data as is, while in IOS it envelops it in another
  637. * Object. Check if IOS and if so return the inner data
  638. *
  639. * @param response -
  640. * Cordova response Object
  641. * @param innerFieldName -
  642. * the name of the inner object to retrieved in IOS
  643. */
  644. this.getCordovaPluginResponseObject = function(response, innerFieldName) {
  645. if (WL.EnvProfile.isEnabled(WL.EPField.ISIOS)) {
  646. if (response) {
  647. return response[innerFieldName];
  648. }
  649. }
  650. return response;
  651. };
  652. }; // End WL.Utils
  653. __WL.prototype.Utils = new __WLUtils;
  654. WL.Utils = new __WLUtils;
  655. /**
  656. * Opens a native dialog using phonegap notification api
  657. */
  658. __WLSimpleDialog = function() {
  659. this.__buttons = null;
  660. this.__dialog = null;
  661. this.__callback = function(result) {
  662. if (WL.Client.getEnvironment() === WL.Env.WINDOWS_PHONE) {
  663. // Nothing to do on WP, since there is no bug there
  664. } else if (WL.EnvProfile.isEnabled(WL.EPField.USES_CORDOVA)) {
  665. // Phonegap bug - native code returns button number instead of
  666. // button index
  667. result--;
  668. } else if (WL.StaticAppProps.ENVIRONMENT == WL.Environment.BLACKBERRY) {
  669. } else {
  670. WL.SimpleDialog.__dialog.hide();
  671. WL.SimpleDialog.__dialog = null;
  672. }
  673. var handler = WL.SimpleDialog.__buttons[result].handler;
  674. WL.SimpleDialog.__buttons = null;
  675. if (handler) {
  676. handler();
  677. }
  678. };
  679. var __validateButtonsObject = function(buttons, callerName) {
  680. if (!WL.Validators.isValidationEnabled) {
  681. return;
  682. }
  683. if ((!buttons) || (buttons.constructor !== Array) || (buttons.length == 0)) {
  684. WL.Validators.logAndThrow("Invalid argument value '" + buttons
  685. + "', expected an array with button descriptors.", callerName);
  686. }
  687. for ( var i = 0; i < buttons.length; i++) {
  688. if (!buttons[i].text || typeof buttons[i].text !== 'string') {
  689. WL.Validators.logAndThrow("Invalid argument value '" + buttons
  690. + "', button descriptor must contain text as string.", callerName);
  691. }
  692. if (buttons[i].handler && typeof buttons[i].handler !== 'function') {
  693. WL.Validators.logAndThrow("Invalid argument value '" + buttons
  694. + "', button descriptor handler must be a function.", callerName);
  695. }
  696. }
  697. };
  698. /**
  699. *
  700. *
  701. * @param title
  702. * The title of the dialog window
  703. * @param text
  704. * The text in the dialog window
  705. * @param buttons
  706. * An array of button descriptors and event handler functions.
  707. * Example: [{text: "OK", handler: function() { ... }}, {text:
  708. * "Cancel", handler: function() { ... }}]
  709. * @param option
  710. * Optional. When native dialog is not available for the current
  711. * environment. An object of the following form: { title: string,
  712. * text: string }
  713. */
  714. this.show = function(title, text, buttons, options) {
  715. var wlDialogContainer = WLJSX.$('WLdialogContainer');
  716. if (!title && !text && wlDialogContainer) {
  717. WLJSX.css(wlDialogContainer, {
  718. display : 'block'
  719. });
  720. return;
  721. }
  722. if (WL.SimpleDialog.__buttons != null) {
  723. WL.Logger.error("WL.SimpleDialog.show() cannot be invoked while dialog is open");
  724. return;
  725. }
  726. WL.Validators.validateArguments([ 'string', 'string', __validateButtonsObject,
  727. WL.Validators.validateObjectOrNull ], arguments, 'WL.SimpleDialog.show');
  728. WL.SimpleDialog.__buttons = buttons;
  729. if (WL.EnvProfile.isEnabled(WL.EPField.USES_CORDOVA)) {
  730. var buttonsArray = [];
  731. for ( var i = 0; i < buttons.length; i++) {
  732. // Phonegap uses comma as the button seperator,
  733. // so we can't use that. Replace commas with a similar character
  734. // (ascii code 130)
  735. buttonsArray[i] = buttons[i].text.replace(",", "‚");
  736. }
  737. if (WL.StaticAppProps.ENVIRONMENT == WL.Env.WINDOWS_PHONE) {
  738. PhoneGap.exec('CustomDialog.show;' + title + ';' + text + ';' + buttonsArray.join(","));
  739. } else {
  740. navigator.notification.confirm(text, WL.SimpleDialog.__callback, title, buttonsArray.join(","));
  741. }
  742. } else if (WL.StaticAppProps.ENVIRONMENT == WL.Environment.BLACKBERRY) {
  743. var buttonTitlesArray = new Array();
  744. for ( var i = 0; i < buttons.length; i++) {
  745. buttonTitlesArray.push(buttons[i].text);
  746. }
  747. var result = blackberry.ui.dialog.customAsk(title + "\n\n" + text, buttonTitlesArray, 0, true);
  748. this.__callback(result);
  749. } else {
  750. var dialogOptions = options || {};
  751. this.__dialog = new WL.Dialog("content", dialogOptions);
  752. var message = '<p>' + text + '</p>';
  753. for ( var i = 0; i < buttons.length; i++) {
  754. message += '<button type="button" class="dialogButton" tabIndex="' + i + '">' + buttons[i].text
  755. + '</button>';
  756. }
  757. this.__dialog.setTitle(title);
  758. this.__dialog.setText(message);
  759. this.__dialog.show();
  760. var dialogButtons = WLJSX.$$('.dialogButton');
  761. for ( var i = 0; i < dialogButtons.length; i++) {
  762. WLJSX.bind(dialogButtons[i], 'click', function(event) {
  763. WL.SimpleDialog.__callback(WLJSX.eventTarget(event).tabIndex);
  764. return false;
  765. });
  766. }
  767. }
  768. };
  769. };
  770. __WL.prototype.SimpleDialog = new __WLSimpleDialog;
  771. WL.SimpleDialog = new __WLSimpleDialog;
  772. __WLApp = function() {
  773. /**
  774. * Opens the specified URL according to the specified target and options
  775. * (specs). The behavior of this method depends on the app environment, as
  776. * follows:
  777. *
  778. * @param url
  779. * Mandatory. The URL of the web page to be opened.
  780. * @param target
  781. * Optional. The value to be used as the target (or name)
  782. * parameter of JavaScript <code>window.open</code> method. If
  783. * no value is specified, <code>_self</code> will be used.
  784. *
  785. * @param options
  786. * Optional. Parameters hash
  787. * @return the opened URL
  788. */
  789. this.openURL = function(url, target, options) {
  790. WL.Validators.validateArguments([ 'string', WL.Validators.validateStringOrNull,
  791. WL.Validators.validateStringOrNull ], arguments, 'WL.App.openURL');
  792. var wnd = null;
  793. if (WLJSX.Object.isUndefined(options) || options === null) {
  794. options = "status=1,toolbar=1,location=1,menubar=1,directories=1,resizable=1,scrollbars=1";
  795. }
  796. if (WLJSX.Object.isUndefined(target) || target === null) {
  797. target = '_self';
  798. }
  799. var absoluteURL = WL.Utils.createAPIRequestURL(url);
  800. switch (WL.StaticAppProps.ENVIRONMENT) {
  801. case WL.Env.OSX_DASHBOARD:
  802. wnd = widget.openURL(absoluteURL);
  803. break;
  804. case WL.Env.VISTA_SIDEBAR:
  805. wnd = window.open(absoluteURL, target, options);
  806. break;
  807. case WL.Env.IPAD:
  808. case WL.Env.IPHONE:
  809. document.location = absoluteURL;
  810. break;
  811. case WL.Env.ADOBE_AIR:
  812. var urlReq = new window.runtime.flash.net.URLRequest(absoluteURL);
  813. wnd = window.runtime.flash.net.navigateToURL(urlReq);
  814. break;
  815. case WL.Env.BLACKBERRY:
  816. var args = new blackberry.invoke.BrowserArguments(absoluteURL);
  817. blackberry.invoke.invoke(blackberry.invoke.APP_BROWSER, args);
  818. break;
  819. default:
  820. if (target === "_self") {
  821. document.location.href = absoluteURL;
  822. } else {
  823. wnd = window.open(absoluteURL, target, options);
  824. }
  825. break;
  826. }
  827. WL.Logger.debug("openURL url: " + absoluteURL);
  828. return wnd;
  829. };
  830. /**
  831. * Returns the locale code according to user's device settings.
  832. *
  833. * @return the user device locale code.
  834. */
  835. this.getDeviceLocale = function() {
  836. if (WL.Client.getEnvironment() == WL.Env.ANDROID) {
  837. return cordova.exec(null, null, "Utils", "getDeviceLocale", []);
  838. } else {
  839. return (navigator.language) ? navigator.language : navigator.userLanguage;
  840. }
  841. };
  842. /**
  843. * Returns the language code according to user's device settings.
  844. *
  845. * @return the user device lanuage code.
  846. */
  847. this.getDeviceLanguage = function() {
  848. return this.getDeviceLocale().substring(0, 2);
  849. };
  850. /**
  851. * Upgrade the inner application. This feature is currently applicable only
  852. * for Android and iOS platforms
  853. */
  854. this.__update = function() {
  855. return;
  856. };
  857. this.getErrorMessage = function(e) {
  858. var message;
  859. if (e === null) {
  860. message = null;
  861. } else if (WLJSX.Object.isString(e)) {
  862. message = e;
  863. } else if (WLJSX.Object.isArray(e)) {
  864. message = e.join(",");
  865. } else if (e.description || e.message) {
  866. // the exception message
  867. message = e.description ? e.description : e.message;
  868. // add file name and line number
  869. if (e.fileName) {
  870. message += " [" + e.fileName + ": line " + e.lineNumber + "]";
  871. } else if (e.sourceURL) {
  872. message += " [" + e.sourceURL + ": line " + e.line + "]";
  873. }
  874. } else {
  875. message = e.toString();
  876. }
  877. return message;
  878. };
  879. // Back Button support (Work on Android && Windows Phone)
  880. this.overrideBackButton = function(callback) {
  881. };
  882. this.resetBackButton = function() {
  883. };
  884. this.copyToClipboard = function(text) {
  885. };
  886. // ////////////////////////////////////////
  887. // Read/Write User Pref on Local Storage
  888. // ////////////////////////////////////////
  889. this.readUserPref = function(key, successCallback, failCallback) {
  890. var msg = "WL.App.readUserPref(..) is supported only on Android and iOS environments";
  891. var ex = new Error(msg);
  892. WL.Logger.error(msg, ex);
  893. throw ex;
  894. };
  895. this.writeUserPref = function(key, value) {
  896. var msg = "WL.App.writeUserPref(..) is supported only on Android and iOS environments";
  897. var ex = new Error(msg);
  898. WL.Logger.error(msg, ex);
  899. throw ex;
  900. };
  901. };
  902. __WL.prototype.App = new __WLApp;
  903. WL.App = new __WLApp;
  904. __WLLogger = function() {
  905. var priority = {
  906. DEBUG : 'DEBUG',
  907. ERROR : 'ERROR'
  908. };
  909. this.__init = function() {
  910. };
  911. this.debug = function(msg, ex) {
  912. log(msg, priority.DEBUG, ex);
  913. };
  914. this.error = function(msg, ex) {
  915. log(msg, priority.ERROR, ex);
  916. };
  917. function log(msg, priority, ex) {
  918. if (typeof msg === 'undefined' || msg === null) {
  919. return;
  920. }
  921. try {
  922. // Translating objects to strings
  923. if (typeof msg != 'string') {
  924. msg = WLJSX.Object.toJSON(msg);
  925. }
  926. } catch (e) {
  927. // there was an exception, cannot log, returning
  928. return;
  929. }
  930. msg = WLJSX.String.stripScripts(msg);
  931. msg = WLJSX.String.escapeHTML(msg);
  932. if (typeof ex !== "undefined") {
  933. msg += " " + WL.App.getErrorMessage(ex);
  934. }
  935. switch (WL.Client.getEnvironment()) {
  936. case WL.Env.ADOBE_AIR:
  937. // Output to Introspector should only be available in debug mode.
  938. if (air.Introspector) {
  939. air.Introspector.Console.log(msg);
  940. }
  941. break;
  942. case WL.Env.OSX_DASHBOARD:
  943. if (typeof window != 'undefind' && typeof window.console != 'undefind' && window.console.log != 'undefind') {
  944. switch (priority) {
  945. case "ERROR":
  946. window.console.error(msg);
  947. break;
  948. case "DEBUG":
  949. window.console.debug(msg);
  950. break;
  951. default:
  952. window.console.log(msg);
  953. }
  954. }
  955. break;
  956. case WL.Env.IPHONE:
  957. case WL.Env.IPAD:
  958. if (typeof (window.debug) != 'undefined') {
  959. switch (priority) {
  960. case "ERROR":
  961. window.debug.error(msg);
  962. break;
  963. case "DEBUG":
  964. window.debug.log(msg);
  965. break;
  966. default:
  967. window.debug.log(msg);
  968. }
  969. }
  970. break;
  971. case WL.Env.ANDROID:
  972. case WL.Env.BLACKBERRY:
  973. case WL.Env.WINDOWS_PHONE:
  974. break;
  975. default:
  976. try {
  977. console.log(msg);
  978. } catch (e) {
  979. }
  980. break;
  981. }
  982. }
  983. /* End Debug Panel */
  984. };
  985. __WL.prototype.Logger = new __WLLogger;
  986. WL.Logger = new __WLLogger;
  987. WL.Response = WLJSX.Class.create({
  988. invocationContext : null,
  989. status : -1,
  990. initialize : function(transport, invocationContext) {
  991. if (transport !== null && typeof transport.status != "undefined") {
  992. this.status = (transport.status || 200);
  993. }
  994. this.invocationContext = invocationContext;
  995. }
  996. });
  997. WL.FailResponse = WLJSX.Class.create(WL.Response, {
  998. errorCode : null,
  999. errorMsg : null,
  1000. initialize : function(__super, transport, invocationContext) {
  1001. __super(transport, invocationContext);
  1002. this.errorCode = transport.responseJSON.errorCode;
  1003. this.errorMsg = transport.responseJSON.errorMsg;
  1004. }
  1005. });
  1006. /*
  1007. * A wrapper for the prototype Ajax.Request. The wrapper is responsible for: 1.
  1008. * Add double-cookie headers to the request. 2. Parse cookies from the response.
  1009. * 3. Invoke the authenticator on demand.
  1010. */
  1011. window.WLJSX.Ajax.WLRequest = WLJSX.Class
  1012. .create({
  1013. // challengeCounter : 0,
  1014. instanceId : null,
  1015. wlAnswers : {},
  1016. initialize : function(url, options) {
  1017. this.options = WLJSX.Object.clone(WLJSX.Ajax.WLRequest.options);
  1018. WLJSX.Object.extend(this.options, options || {});
  1019. this.url = WL.Utils.createAPIRequestURL(url);
  1020. this.callerOptions = options;
  1021. this.isTimeout = false;
  1022. this.timeoutTimer = null;
  1023. // this.stopPolling = false;
  1024. this.options.onSuccess = this.onWlSuccess.bind(this);
  1025. this.options.onFailure = this.onWlFailure.bind(this);
  1026. // Handle Exceptions
  1027. this.options.onException = this.onException.bind(this);
  1028. // 0 is the response status when the host is unresponsive
  1029. // (server is
  1030. // down)
  1031. this.options.on0 = this.onUnresponsiveHost.bind(this);
  1032. // Appending the cookie headers to possibly existing ones.
  1033. // If you pass additional headers make sure to use objects of
  1034. // name-value
  1035. // pairs (and not arrays).
  1036. // this.options.requestHeaders =
  1037. // Object.extend(CookieManager.createCookieHeaders(),
  1038. // this.options.requestHeaders || {});
  1039. this.options.requestHeaders = WL.CookieManager.createCookieHeaders();
  1040. // For GET requests - preventing Vista from returning cached GET
  1041. // ajax
  1042. // responses.
  1043. // For POST requests - preventing Air from sending a GET request
  1044. // if the
  1045. // request has no body (even if
  1046. // it's declared as a POST request).
  1047. if (WLJSX.Object.isUndefined(this.options.parameters) || this.options.parameters === null
  1048. || this.options.parameters === "") {
  1049. this.options.parameters = {};
  1050. }
  1051. // Add a parameter to notify that this is an Ajax request - for
  1052. // Air.
  1053. this.options.parameters.isAjaxRequest = "true";
  1054. this.sendRequest();
  1055. },
  1056. sendRequest : function() {
  1057. WL.Logger.debug("Request [" + this.url + "]");
  1058. // Update the random before every request to prevent caching.
  1059. this.options.parameters.x = Math.random();
  1060. // Cookie headers must be updated at this point, since they may
  1061. // have
  1062. // changed
  1063. // since the request has been created.
  1064. this.options.requestHeaders = WL.CookieManager.createCookieHeaders();
  1065. this.options.requestHeaders["x-wl-app-version"] = WL.StaticAppProps.APP_VERSION;
  1066. // Send the challenge response data in case we get challenge
  1067. // from the
  1068. // sever
  1069. // Authenticity - need to remove when doing authenticity CP
  1070. if (arguments[0]) {
  1071. var challenge = arguments[0].challenge;
  1072. if (challenge != null) {
  1073. this.options.requestHeaders["WL-Challenge-Response-Data"] = challenge;
  1074. }
  1075. }
  1076. // add Authorization header from wlAnswres
  1077. if (typeof this.wlAnswers != "undefined") {
  1078. var authJson = {};
  1079. var shouldSendAuthHeader = false;
  1080. for ( var realm in this.wlAnswers) {
  1081. if (Object.prototype.hasOwnProperty.call(this.wlAnswers, realm)) {
  1082. answer = "";
  1083. try {
  1084. answer = JSON.parse(this.wlAnswers[realm]);
  1085. } catch (e) {
  1086. answer = this.wlAnswers[realm];
  1087. }
  1088. // Validate we are working with standrad JSON
  1089. if (typeof answer == "string" && typeof JSON == "undefined") {
  1090. authJson[realm] = answer.indexOf("\"") == 0 ? answer : "\"" + answer + "\"";
  1091. } else {
  1092. authJson[realm] = answer;
  1093. }
  1094. shouldSendAuthHeader = true;
  1095. }
  1096. }
  1097. if (shouldSendAuthHeader == true) {
  1098. this.options.requestHeaders.Authorization = WLJSX.Object.toJSON(authJson);
  1099. // init the wlAnswer map...
  1100. this.wlAnswers = {};
  1101. }
  1102. }
  1103. // add headers from WL.Client.globalHeaders
  1104. if ((typeof WL.Client.__globalHeaders != "undefined") && (WL.Client.__globalHeaders != null)) {
  1105. for ( var headerName in WL.Client.__globalHeaders) {
  1106. if (Object.prototype.hasOwnProperty.call(WL.Client.__globalHeaders, headerName)) {
  1107. this.options.requestHeaders[headerName] = WL.Client.__globalHeaders[headerName];
  1108. }
  1109. }
  1110. }
  1111. if (this.options.timeout > 0) {
  1112. this.timeoutTimer = window.setTimeout(this.handleTimeout.bind(this), this.options.timeout);
  1113. }
  1114. new WLJSX.Ajax.Request(this.url, this.options);
  1115. },
  1116. onWlSuccess : function(transport) {
  1117. if (this.isTimeout) {
  1118. return;
  1119. }
  1120. this.cancelTimeout();
  1121. var containsChallenges = WL.Client.checkResponseForChallenges(this, transport);
  1122. if (!containsChallenges) {
  1123. this.onSuccess(transport);
  1124. }
  1125. },
  1126. onSuccess : function(transport) {
  1127. WLJSX.Ajax.WLRequest.setConnected(true);
  1128. if (transport.getAllHeaders() !== null) {
  1129. // Handle Cookies:
  1130. var headers = transport.getAllHeaders().split("\n");
  1131. WL.CookieManager.handleResponseHeaders(headers);
  1132. }
  1133. WL.Logger.debug("response [" + this.url + "] success: " + transport.responseText);
  1134. // In vista - the responseJSON is not auto generated.
  1135. if (WL.StaticAppProps.ENVIRONMENT == WL.Env.VISTA_SIDEBAR) {
  1136. if (this.options.evalJSON && transport.responseText !== null && transport.responseText !== ''
  1137. && (WLJSX.Object.isUndefined(transport.responseJSON) || transport.responseJSON === null)) {
  1138. try {
  1139. transport.responseJSON = WLJSX.String.evalJSON(transport.responseText, true);
  1140. } catch (e) {
  1141. transport.responseJSON = {
  1142. errorCode : WL.ErrorCode.UNEXPECTED_ERROR,
  1143. errorMsg : WL.ClientMessages.unexpectedError
  1144. };
  1145. WL.Logger.error("[" + this.url + "] parsing failure. response: "
  1146. + transport.responseJSON.errorMsg);
  1147. if (typeof (this.callerOptions.onFailure) == "function") {
  1148. this.callerOptions.onFailure(transport);
  1149. }
  1150. return;
  1151. }
  1152. }
  1153. }
  1154. // Handle notification subscription for push (if need)
  1155. if (transport.responseJSON && transport.responseJSON.notificationSubscriptionState
  1156. && WL.Client.Push.__isDeviceSupportPush()) {
  1157. handleSubscriptions(transport.responseJSON.notificationSubscriptionState);
  1158. }
  1159. if (typeof (this.callerOptions.onSuccess) == "function") {
  1160. this.callerOptions.onSuccess(transport);
  1161. }
  1162. },
  1163. onWlFailure : function(transport) {
  1164. if (this.isTimeout) {
  1165. return;
  1166. }
  1167. this.cancelTimeout();
  1168. var containsChallenges = WL.Client.checkResponseForChallenges(this, transport);
  1169. if (!containsChallenges) {
  1170. this.onFailure(transport);
  1171. }
  1172. },
  1173. onFailure : function(transport) {
  1174. // sometimes onFailure is called with a dummy transport object
  1175. // for example when an authentication timeout occurs.
  1176. if (transport && transport.getAllHeaders && transport.getAllHeaders() !== null) {
  1177. var headers = transport.getAllHeaders().split("\n");
  1178. WL.CookieManager.handleResponseHeaders(headers);
  1179. }
  1180. if (transport.responseJSON === null) {
  1181. try {
  1182. transport.responseJSON = WLJSX.String.evalJSON(transport.responseText, true);
  1183. } catch (e) {
  1184. transport.responseJSON = {
  1185. errorCode : WL.ErrorCode.UNEXPECTED_ERROR,
  1186. errorMsg : WL.ClientMessages.unexpectedError
  1187. };
  1188. }
  1189. }
  1190. if (transport.responseJSON.errorCode != WL.ErrorCode.REQUEST_TIMEOUT
  1191. && transport.responseJSON.errorCode != WL.ErrorCode.UNRESPONSIVE_HOST) {
  1192. WLJSX.Ajax.WLRequest.setConnected(true);
  1193. }
  1194. var callbackHandler = this.getCallbackForErrorCode(transport.responseJSON.errorCod