AnnotationHelper.js 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625
  1. /*
  2. *+------------------------------------------------------------------------+
  3. *| Licensed Materials - Property of IBM
  4. *| IBM Cognos Products: Viewer
  5. *| (C) Copyright IBM Corp. 2001, 2013
  6. *|
  7. *| US Government Users Restricted Rights - Use, duplication or
  8. *| disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
  9. *|
  10. *+------------------------------------------------------------------------+
  11. */
  12. dojo.provide("viewer.AnnotationHelper");
  13. dojo.declare("viewer.AnnotationHelper", null, {
  14. m_loadAnnotationsDfd : null,
  15. //This records if any annotation is returned on the first getAnnotation call. if none is returned, we want to skip getAnnotation call.
  16. //default value is true. responseHandler of getAnnotations update this flag accordingly.
  17. //If a user select 'reset' action, this flag reset to 'true' so that we issue getAnnotation call.
  18. m_bCallGetAnnotations : true,
  19. m_bAnnotationsEnabled : null,
  20. constructor : function(iWidget) {
  21. this.m_viewerIWidget = iWidget;
  22. this.m_bCallGetAnnotations = true;
  23. this.m_bAnnotationsEnabled = null;
  24. },
  25. getAnnotationStore : function() {
  26. return this.m_viewerIWidget.getAnnotationStore();
  27. },
  28. setCallGetAnnotations : function(flag) {
  29. this.m_bCallGetAnnotations = flag;
  30. },
  31. isEnabled : function() {
  32. if(this.m_bAnnotationsEnabled === null) {
  33. this.m_bAnnotationsEnabled = this.m_viewerIWidget.getViewerObject().bBuxAnnotationsAvailable;
  34. }
  35. return this.m_bAnnotationsEnabled;
  36. },
  37. refreshAnnotationData : function() {
  38. if(this.m_loadAnnotationsDfd) {
  39. return null;
  40. }
  41. this.m_loadAnnotationsDfd = new dojo.Deferred();
  42. this.fetchAnnotationData();
  43. return this.m_loadAnnotationsDfd;
  44. },
  45. /**
  46. * Sends a request to the server for the latest annotation data
  47. */
  48. fetchAnnotationData : function() {
  49. var viewerIWidget = this.m_viewerIWidget;
  50. if (!this.m_bCallGetAnnotations || !this.isEnabled()) { //stop proceede if the flag is false
  51. return;
  52. }
  53. dojo.when(viewerIWidget.getWidgetStoreID(),
  54. dojo.hitch(this, function(widgetStoreID) {
  55. if(!widgetStoreID) {
  56. return;
  57. }
  58. this.m_viewerIWidget.getLoadManager().runWhenHasViewer(
  59. dojo.hitch(this, this._fetchAnnotationData, widgetStoreID)
  60. );
  61. })
  62. );
  63. },
  64. _fetchAnnotationData: function(widgetStoreID) {
  65. var cognosViewer = this.m_viewerIWidget.getViewerObject();
  66. var selCon = cognosViewer.getSelectionController();
  67. var metadata = selCon.getCCDManager().m_md;
  68. if(!metadata) {
  69. metadata = {};
  70. }
  71. metadata = dojo.toJson(metadata);
  72. var contextData = selCon.getCCDManager().m_cd;
  73. if(!contextData) {
  74. contextData = {};
  75. }
  76. contextData = dojo.toJson(contextData);
  77. var callbacks = {"complete":{}, "fault": {}};
  78. callbacks.complete["object"] = this;
  79. callbacks.complete["method"] = this.fetchAnnotationDataResponse;
  80. callbacks.fault["object"] = this;
  81. callbacks.fault["method"] = this.fetchAnnotationDataResponseFault;
  82. var asynchRequest = new AsynchJSONDispatcherEntry(cognosViewer);
  83. asynchRequest.setCallbacks(callbacks);
  84. asynchRequest.addFormField("widgetStoreID", widgetStoreID);
  85. asynchRequest.addFormField("ui.action", "getAnnotations");
  86. asynchRequest.addFormField("cv.metatdata", metadata);
  87. asynchRequest.addFormField("cv.context", contextData);
  88. // Need to bypass the queue for this request since it's a background request and
  89. // we don't want other requests (actions) to get dropped from the queue
  90. asynchRequest.sendRequest();
  91. },
  92. fetchAnnotationDataResponseFault: function(oAsynchResponse) {
  93. this.m_bCallGetAnnotations = false;
  94. var oFaultDialog = new FaultDialog(this.m_viewerIWidget.getViewerObject());
  95. var oSoapFault = oAsynchResponse.getSoapFault();
  96. var sErrorCode = null;
  97. var nException = XMLHelper_FindChildByTagName(oSoapFault, "exception", true);
  98. if(nException) {
  99. var nErrorCode = XMLHelper_FindChildByTagName(nException, "errorCode", false);
  100. if(nErrorCode) {
  101. sErrorCode = XMLHelper_GetText(nErrorCode);
  102. }
  103. }
  104. if(sErrorCode === "0") {
  105. var sMessage = null;
  106. var nMessage = XMLHelper_FindChildByTagName(nException, "message", false);
  107. if(nMessage) {
  108. var nMessageString = XMLHelper_FindChildByTagName(nMessage, "messageString", true);
  109. if(nMessageString) {
  110. sMessage = XMLHelper_GetText(nMessageString, false);
  111. }
  112. }
  113. if(sMessage) {
  114. var rErrorCode = /ANS-GEN-(\d{2,4})/;
  115. var aMatches = rErrorCode.exec(sMessage);
  116. if(aMatches && aMatches.length && aMatches.length > 1) {
  117. var sAnsErrorCode = aMatches[1];
  118. if(sAnsErrorCode === "0075") {
  119. //Parent deleted - i.e. widget has been deleted.
  120. oFaultDialog.setErrorMessage(RV_RES.IDS_ANNOTATION_WIDGET_DELETED_ERROR);
  121. }
  122. }
  123. }
  124. }
  125. //Delete all annotations (they're no longer valid).
  126. this._cleanupPreviousAnnotations();
  127. this.getAnnotationStore().clear();
  128. oFaultDialog.show(oSoapFault);
  129. if(this.m_loadAnnotationsDfd) {
  130. this.m_loadAnnotationsDfd.errback();
  131. this.m_loadAnnotationsDfd = null;
  132. }
  133. },
  134. fetchAnnotationDataResponse : function(asynchJSONResponse) {
  135. var editContentAction = window["CVEditContentActionInstance"];
  136. var jsonResult = asynchJSONResponse.getResult();
  137. //Prevent subsequent queries for annotations only if the report
  138. //has no annotations at all (i.e. jsonResult is null, not empty).
  139. this.m_bCallGetAnnotations = this.m_bCallGetAnnotations && jsonResult !== null;
  140. if (jsonResult===null) {
  141. jsonResult = [];
  142. }
  143. var viewerObject = this.m_viewerIWidget.getViewerObject();
  144. viewerObject.envParams["cv.annotationData"] = jsonResult;
  145. this._cleanupPreviousAnnotations();
  146. if (jsonResult.length > 0) {
  147. if (this.getAnnotationStore()) {
  148. var annotationArray = this._generateMatchedAnnotationsFromViewerObject();
  149. this.getAnnotationStore().load(annotationArray);
  150. this.displayCommentIndicators();
  151. }
  152. }
  153. if(this.m_loadAnnotationsDfd) {
  154. this.m_loadAnnotationsDfd.callback();
  155. this.m_loadAnnotationsDfd = null;
  156. }
  157. },
  158. /*
  159. * destroy all commentViewer widget for previous annotations
  160. */
  161. _cleanupPreviousAnnotations : function () {
  162. var store = this.getAnnotationStore();
  163. if (store) {
  164. var annotations = store.getAll();
  165. //clean up all annotations
  166. for (var contextId in annotations) {
  167. var commentId = this.m_viewerIWidget.getWidgetId() + "_" + contextId + "_comment";
  168. var commentViewer = dijit.byId(commentId);
  169. if (typeof commentViewer != "undefined" && commentViewer != null) {
  170. commentViewer.destroy();
  171. delete commentViewer;
  172. }
  173. store.clear(contextId);
  174. }
  175. }
  176. },
  177. /*
  178. * Returns array of annotations. Ctx of an annotation is updated with the explicit ctx value of the report cell the annotation is on.
  179. * In order to update ctx value, it does the following.
  180. *
  181. * - remove any OR (|) operator in ctxValue
  182. * - find a matching report cell and take ctx value of it
  183. *
  184. */
  185. _generateMatchedAnnotationsFromViewerObject : function () {
  186. var viewerObject = this.m_viewerIWidget.getViewerObject();
  187. var annotationData = [];
  188. if (viewerObject && viewerObject.envParams && viewerObject.envParams["cv.annotationData"]) {
  189. annotationData = eval(viewerObject.envParams["cv.annotationData"]);
  190. }
  191. var annotationListWithUniqueCTX = this._generateAnnotationListWithoutORoperator(annotationData);
  192. return this._updateAnnotationCtxWithMatchedCellCtx(annotationListWithUniqueCTX, viewerObject);
  193. },
  194. /*
  195. * ctx of an annotation may have 'OR' operator.
  196. * for example, 9:3|4:*
  197. * It means that annotated cell's ctx could be either 9:3:* or 9:4:*
  198. *
  199. * This function removes 'OR' operator and make two annotations with one of each possible ctx value.
  200. *
  201. */
  202. _generateAnnotationListWithoutORoperator : function(annotationData) {
  203. var annotationListWithUniqueCTX = [];
  204. for (var i=0, len=annotationData.length; i<len; i++ ) {
  205. var anno = annotationData[i];
  206. if(anno.ctx) { //cell level annotation
  207. var oneOrMoreAnno = bux.AnnotationHelper.generateCTXList(anno.ctx);
  208. for(var j=0, jLen=oneOrMoreAnno.length; j<jLen; j++) {
  209. var newAnno = {
  210. ann:anno.ann, // serviceId
  211. lmt:anno.lmt, // modified date/time
  212. lmtf:anno.lmtf, // modified date/time (formatted)
  213. ctx:anno.ctx,
  214. desc:anno.desc, // text
  215. fd:anno.fd, //filter data
  216. layoutElementId:anno.layoutElementId,
  217. owner:anno.owner, //owner name string
  218. ownerSearchPath:anno.ownerSearchPath,
  219. pv:anno.pv, //prompt param values
  220. rdi:anno.rdi,
  221. sd:anno.sd, //sliders data
  222. version:anno.version || 1
  223. };
  224. newAnno.ctx = oneOrMoreAnno[j];
  225. annotationListWithUniqueCTX.splice(0,0, newAnno);
  226. }
  227. } else {//widget level annotation
  228. annotationListWithUniqueCTX.splice(0,0, anno);
  229. }
  230. }
  231. return annotationListWithUniqueCTX;
  232. },
  233. /*
  234. * Finds the report cell of an annotations, and update ctx of annotation with the cell's ctx
  235. * Returns array of annotations which all has explicit ctx value
  236. *
  237. * In order to that, it does the following
  238. *
  239. * first, creates AnnotationCTXLookup object, and
  240. * calls populateCtxDetailsForAllAnnotations to load ctx details for all Ids in annotation ctx
  241. *
  242. * then, for each annotation
  243. *
  244. * - queries dom nodes with ctx attirbute, report cells, if hasn't
  245. * - if ctx of an annotation is not present, it is a widget level. put it in the return array
  246. * - calls isAnnotatedCell function of AnnotationCTXLookup with annotation and each cell's ctx value.
  247. * - only if the function return true,
  248. * updates ctx of annotation with the ctx value of the cell. and put it in the return array
  249. *
  250. */
  251. _updateAnnotationCtxWithMatchedCellCtx : function (newAnnotationListWithUniqueCTX, viewerObject) {
  252. var processedAnnotationList = [];
  253. var ctxLookup = new AnnotationCTXLookup(this.m_viewerIWidget.getViewerObject().getSelectionController().getCCDManager());
  254. ctxLookup.populateCtxDetailsForAllAnnotations(newAnnotationListWithUniqueCTX);
  255. var nodes = [];
  256. for(var i=0, len=newAnnotationListWithUniqueCTX.length; i<len; i++) {
  257. var anno = newAnnotationListWithUniqueCTX[i];
  258. if (anno.ctx) {
  259. if (nodes.length === 0) {
  260. //query now. we need it for cell level handling
  261. nodes = dojo.query('[ctx]', this.m_viewerIWidget.iContext.getRootElement());
  262. }
  263. for (var j = 0, jLen = nodes.length; j < jLen; j++) {
  264. var cellCtxValue = nodes[j].getAttribute('ctx'); // get ctx attributes from node
  265. if (ctxLookup.isAnnotatedCell(anno, cellCtxValue)) {
  266. anno.ctx = cellCtxValue;
  267. processedAnnotationList.splice(0,0, anno);
  268. break;
  269. }
  270. }
  271. } else {
  272. processedAnnotationList.splice(0,0, anno);
  273. }
  274. }
  275. return processedAnnotationList;
  276. },
  277. displayCommentIndicators : function () {
  278. var store = this.getAnnotationStore();
  279. var commentedCells = store.getAll();
  280. for (var cell in commentedCells)
  281. {
  282. var indicator = new bux.AnnotationIndicator({annotationStore: store, context: cell, iWidgetContainer: this.m_viewerIWidget, dir: this.m_viewerIWidget.getViewerObject().getDirection()});
  283. indicator.addExistingCommentToCell();
  284. }
  285. },
  286. /**
  287. * Runs the placement logic on each annotation indicator again,
  288. * incase the positions where they should be have changed.
  289. */
  290. repositionCommentIndicators : function() {
  291. var store = this.getAnnotationStore();
  292. var annotations = store.getAll();
  293. for (var id in annotations) {
  294. var annotation = annotations[id];
  295. var ctx = annotation[0].getContext();
  296. var indicatorId = store.getIndicatorWidgetId(ctx);
  297. if (indicatorId!==null) {
  298. var indicator = dijit.byId(indicatorId);
  299. indicator.addToPage();
  300. }
  301. }
  302. },
  303. promptForSave : function(yesOkFunc) {
  304. dojo["require"]("bux.dialogs.InformationDialog"); //@lazyload
  305. var saveConfirmationDialog = new bux.dialogs.InformationDialog({
  306. title: RV_RES.IDS_JS_COMMENT_DLG_TITLE,
  307. sMainMessage: RV_RES.IDS_JS_COMMENT_DLG_MESSAGE,
  308. sDescription: RV_RES.IDS_JS_COMMENT_DLG_DETAILS,
  309. sInfoIconClass: 'bux-informationDialog-warning-icon',
  310. buttons : ['YES','NO'],
  311. yesOKHandler : yesOkFunc
  312. });
  313. saveConfirmationDialog.startup();
  314. saveConfirmationDialog.show();
  315. },
  316. addComment : function (ctxId, cellValue) {
  317. if (this.m_viewerIWidget.isSaveNecessary()) {
  318. this.promptForSave( dojo.hitch(this, this.onCommentSaveAcknowledge, ctxId, cellValue) );
  319. } else {
  320. this.addNewComment(ctxId, cellValue);
  321. }
  322. },
  323. editComment : function (ctxId) {
  324. var comment = bux.getComment(this.m_viewerIWidget.iContext, this.getAnnotationStore().getEffectiveIds(ctxId));
  325. if (comment && comment.edit)
  326. {
  327. comment.edit();
  328. }
  329. },
  330. deleteComment : function (ctxId) {
  331. this.getAnnotationStore().deleteOneComment(ctxId);
  332. /* THE following function should be added as a callback function of the deleteOneComment above.
  333. * The deleteOneComment function must be modified to return the deferred object.
  334. * Commenting this logic for now because BUX streamlining work is in progress.
  335. *
  336. this.m_bCallGetAnnotations = this.annotationStore.hasAnnotation();
  337. */
  338. },
  339. addNewComment : function(ctxId, cellValue) {
  340. //If cellValue is undefined or null, don't prepopulate flyout
  341. this.addAsNewComment(ctxId, (cellValue == null) ? "" : (cellValue + ' - '));
  342. },
  343. addAsNewComment : function(ctxId, text) {
  344. var indicator = null;
  345. var contextId = (ctxId===null)? this.getAnnotationStore().WIDGET_CONTEXT: ctxId;
  346. var indicatorId = this.getAnnotationStore().getIndicatorWidgetId(contextId);
  347. if (indicatorId!=null) {
  348. indicator = dijit.byId(indicatorId);
  349. }
  350. if (indicator==null) {
  351. dojo["require"]("bux.AnnotationIndicator"); //@lazyload
  352. indicator = new bux.AnnotationIndicator({
  353. annotationStore: this.getAnnotationStore(),
  354. context: contextId,
  355. iWidgetContainer: this.m_viewerIWidget,
  356. dir: this.m_viewerIWidget.getViewerObject().getDirection()
  357. });
  358. window.setTimeout(function () { indicator.addNewCommentToCell(text); },0);
  359. } else {
  360. window.setTimeout(function () { indicator.comment.editNewComment(contextId, text); },0);
  361. }
  362. },
  363. onCommentSaveAcknowledge : function(ctxId, cellValue) {
  364. this.m_viewerIWidget._pendingContextId = ctxId;
  365. this.m_viewerIWidget._pendingCellValue = cellValue;
  366. this.m_viewerIWidget.fireEvent('com.ibm.bux.widget.action', null, {action: 'canvas.save'});
  367. },
  368. addWidgetComment : function () {
  369. if (this.m_viewerIWidget.isSaveNecessary()) {
  370. this.promptForSave( dojo.hitch(this, this.onCommentSaveAcknowledge, null, this.m_viewerIWidget.getDisplayName()) );
  371. } else {
  372. this.addNewComment(null, this.m_viewerIWidget.getDisplayName());
  373. }
  374. },
  375. editWidgetComment : function () {
  376. var comment = bux.getComment(this.m_viewerIWidget.iContext, [this.getAnnotationStore().WIDGET_CONTEXT]);
  377. if (comment && comment.edit)
  378. {
  379. comment.edit();
  380. }
  381. },
  382. deleteWidgetComment : function () {
  383. this.deleteComment(this.getAnnotationStore().WIDGET_CONTEXT);
  384. },
  385. commitComment : function(annotation) {
  386. //If it has never been loaded, it's a brand new comment
  387. if (annotation.getContext() !== this.getAnnotationStore().WIDGET_CONTEXT) {
  388. return this.commitCellComment(annotation);
  389. }
  390. else {
  391. return this.commitWidgetComment(annotation, this.getAnnotationStore());
  392. }
  393. },
  394. /**
  395. * @return a deferred which will be resolved when the request to the server
  396. * to commit a cell comment returns.
  397. */
  398. commitCellComment : function(annotation) {
  399. //Fire off a request to Viewer to commit the annotation
  400. //Note: Edit requests go directly to the annotation service and not through Viewer,
  401. //so they are not dealt with here
  402. var deferred = new dojo.Deferred();
  403. var cognosViewer = this.m_viewerIWidget.getViewerObject();
  404. var callbacks = {
  405. customArguments:[annotation, deferred],
  406. "complete": {"object": this, "method": this.handleCellCommentSaveResponse},
  407. "fault": {"object": this, "method": this.handleCellCommentSaveErrorResponse},
  408. "error": {"object": this, "method": this.handleCellCommentSaveServerErrorResponse}
  409. };
  410. var asynchRequest = new AsynchJSONDispatcherEntry(cognosViewer);
  411. asynchRequest.setCallbacks( callbacks );
  412. this.preparePostForCommitCellComment( asynchRequest, annotation ).then(
  413. function() {
  414. cognosViewer.dispatchRequest(asynchRequest);
  415. }
  416. );
  417. return deferred;
  418. },
  419. /**
  420. * @return a deferred which will be resolved when all form fields are added to the request
  421. */
  422. preparePostForCommitCellComment : function(asynchRequest, annotation) {
  423. var dfd = new dojo.Deferred();
  424. dojo.when(this.m_viewerIWidget.getWidgetStoreID(),
  425. dojo.hitch(this, function(widgetStoreID) {
  426. var viewerObject = this.m_viewerIWidget.getViewerObject();
  427. var selCon = viewerObject.getSelectionController();
  428. asynchRequest.addFormField("widgetStoreID", widgetStoreID);
  429. asynchRequest.addFormField("ui.action", "commentSave");
  430. asynchRequest.addFormField("cv.metatdata", dojo.toJson(selCon.getCCDManager().m_md));
  431. asynchRequest.addFormField("cv.context", dojo.toJson(selCon.getCCDManager().m_cd));
  432. asynchRequest.addFormField("cv.commentId", annotation.getContext());
  433. asynchRequest.addFormField("cv.commentDesc", xml_encode(annotation.getDescription()));
  434. var lid = selCon.getAllSelectedObjects()[0].getLayoutElementId();
  435. if (lid) {
  436. //The "lid" attribute is composed of layout ID + namespacePrefix + widget identifier.
  437. //We only want the layout ID, so remove the rest.
  438. lid = lid.replace(this.m_viewerIWidget.getViewerId(), "");
  439. annotation.setParentId(lid);
  440. asynchRequest.addFormField("cv.commentLayoutId", annotation.getParentId());
  441. var annInfoBar = new AnnotationInfoBar(viewerObject, lid);
  442. var filterContext = annInfoBar.createFilterContext();
  443. if (filterContext!=null) {
  444. annotation.setFilterContext(filterContext);
  445. if (filterContext.getPromptsJSON()) {
  446. asynchRequest.addFormField("cv.filterContext_prompts", dojo.toJson(filterContext.getPromptsJSON()));
  447. }
  448. if (filterContext.getFilterJSON()) {
  449. asynchRequest.addFormField("cv.filterContext_filter", dojo.toJson(filterContext.getFilterJSON()));
  450. }
  451. if (filterContext.getSlidersJSON()) {
  452. asynchRequest.addFormField("cv.filterContext_sliders", dojo.toJson(filterContext.getSlidersJSON()));
  453. }
  454. }
  455. }
  456. dfd.callback();
  457. })
  458. );
  459. return dfd;
  460. },
  461. /**
  462. * @return a deferred that resolves when the server responds to new annotation request
  463. */
  464. commitWidgetComment : function(annotation) {
  465. dojo["require"]("bux.Services"); //@lazyload
  466. var serviceURL = bux.Services.getGateway() + "/annotationService/creation";
  467. var contentObj = {};
  468. contentObj["annotationName"] = annotation.getName();
  469. if (contentObj["annotationName"] == null) {
  470. //This parameter is necessary to the API -- the call will fail without it
  471. contentObj["annotationName"] = "";
  472. }
  473. contentObj["annotationDescription"] = annotation.getDescription();
  474. var dfd = new dojo.Deferred();
  475. dojo.when(this.m_viewerIWidget.getWidgetStoreID(),
  476. dojo.hitch(this, function(widgetStoreID) {
  477. contentObj["annotationParentID"] = widgetStoreID;
  478. bux.xhrPost({
  479. url: serviceURL,
  480. sync: true,
  481. content: contentObj
  482. }).then(
  483. /*callback*/ dojo.hitch( this, function (response) {
  484. this.handleCommentSaveDone(response, annotation, this.getAnnotationStore(), this.m_viewerIWidget);
  485. annotation.loadDetails();
  486. dfd.callback();
  487. })
  488. );
  489. })
  490. );
  491. return dfd;
  492. },
  493. handleCellCommentSaveResponse : function(asynchJSONResponse, annotation, deferred)
  494. {
  495. var responseObject = asynchJSONResponse.getJSONResponseObject();
  496. if (responseObject) {
  497. var jsonResult = responseObject.json;
  498. if (jsonResult) {
  499. var result = this.handleCommentSaveDone(jsonResult, annotation, this.getAnnotationStore(), this.m_viewerIWidget);
  500. if (typeof result != 'Error') {
  501. annotation.loadDetails();
  502. }
  503. }
  504. }
  505. deferred.callback(asynchJSONResponse);
  506. },
  507. handleCellCommentSaveErrorResponse: function(asynchJSONError, annotation, deferred) {
  508. deferred.errback(new Error(asynchJSONError.getSoapFaultDetailMessageString()));
  509. },
  510. handleCellCommentSaveServerErrorResponse: function(error, annotation, deferred) {
  511. var errorObject = new Error(error.xmlHttp.statusText);
  512. //Include the server error response code so the user can diagnose his web server
  513. errorObject.xhr = error.xmlHttp;
  514. deferred.errback(errorObject);
  515. },
  516. //TODO: we shouldn't need to pass viewerWidget to this function, we could simply use this.m_viewerIWidget to get the widget
  517. handleCommentSaveDone : function(response, annotation, store, viewerWidget) {
  518. var xmlDom = XMLBuilderLoadXMLFromString(response);
  519. if (xmlDom) {
  520. var responseNode = xmlDom.firstChild;
  521. var annotationNode = XMLHelper_FindChildByTagName(responseNode, "annotation", false);
  522. if (annotationNode) {
  523. var annotationIdNode = XMLHelper_FindChildByTagName(annotationNode, "id", false);
  524. if (annotationIdNode) {
  525. var annotationId = XMLHelper_GetText(annotationIdNode);
  526. annotation.setServiceId(annotationId);
  527. annotation.setIWidgetContainer(viewerWidget);
  528. store.setWidgetContainer(viewerWidget);
  529. this.setCallGetAnnotations(true);
  530. return response;
  531. }
  532. }
  533. }
  534. return new Error(response.toString());
  535. }
  536. });