ActiveReportIWidget.js 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080
  1. /*
  2. *+------------------------------------------------------------------------+
  3. *| Licensed Materials - Property of IBM
  4. *| IBM Cognos Products: Viewer
  5. *| (C) Copyright IBM Corp. 2015
  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.require("dojo.string");
  13. dojo.require("dojo._base.array");
  14. dojo.require("bux.dialogs.WidgetPropertiesFromJSON");
  15. dojo.require("ActiveReportIWidgetProperties");
  16. dojo.require("bux.IWidgetUtils");
  17. dojo.provide("ActiveReportIWidget");
  18. var globalActiveViewerIdentifier = 1;
  19. dojo.declare("ActiveReportIWidget", bux.reportViewer, {
  20. namespacePrefix: "a",
  21. iframe: null,
  22. ACTIVEREPORT_VERSION: "2", //Caspian verion = '2'
  23. EVENT_NAME_FILTER_ITEMS_GET: 'com.ibm.bux.filter.items.get',
  24. EVENT_NAME_FILTER_ITEMS_GET_DONE: 'com.ibm.bux.filter.items.get.done',
  25. EVENT_NAME_FILTER_VALUES_GET: 'com.ibm.bux.filter.values.get',
  26. EVENT_NAME_FILTER_VALUES_GET_DONE: 'com.ibm.bux.filter.values.get.done',
  27. m_isActiveReportOutputPreCaspianVersion: false,
  28. m_sActiveReportOutputVersion: null,
  29. m_oPublicVariableNames: null,
  30. m_oCanvasContext: null,
  31. m_oCanvasContextCollection: null,
  32. m_oSelectionFilterBasePayload: null,
  33. m_bApplicationLoaded: false,
  34. m_aWaitUntilLoadedQueue: null,
  35. m_sDivHeight: null,
  36. m_sDivWidth: null,
  37. m_oWidgetContextManager: null,
  38. constructor: function() {
  39. this.viewerIdentifier = (globalActiveViewerIdentifier++).toString();
  40. this.m_aWaitUntilLoadedQueue = [];
  41. this.m_oPublicVariableNames = null;
  42. this.m_oSelectionFilterBasePayload = null;
  43. this.m_oCanvasContextCollection = {};
  44. this.m_oWidgetContextManager = new WidgetContextManager(this);
  45. },
  46. getViewerId: function() {
  47. return this.namespacePrefix + this.viewerIdentifier;
  48. },
  49. getIFrameId: function() {
  50. return "CVIFrame" + this.getViewerId();
  51. },
  52. getContentId: function() {
  53. return "RVContent" + this.getViewerId();
  54. },
  55. getLoadingId: function() {
  56. return "loading" + this.getViewerId();
  57. },
  58. getDisplayName: function() {
  59. return this.getAttributeValue("widgetTitle");
  60. },
  61. getAttributeValue: function(name) {
  62. return this.iContext.getiWidgetAttributes().getItemValue(name);
  63. },
  64. getApplication: function () {
  65. if (this.iframe && this.iframe.contentWindow && this.iframe.contentWindow.Application) {
  66. return this.iframe.contentWindow.Application;
  67. }
  68. return null;
  69. },
  70. getIFrameDocument: function() {
  71. if (this.iframe.contentDocument) {
  72. //Firefox
  73. return this.iframe.contentDocument;
  74. }
  75. if (this.iframe.contentWindow) {
  76. //IE 8
  77. return this.iframe.contentWindow.document;
  78. }
  79. return null; //fail
  80. },
  81. onLoad: function() {
  82. this.inherited(arguments);
  83. var reportStoreID = this.getAttributeValue("originalReport");
  84. var properties = this.getAttributeValue( "viewerProperties");
  85. this.properties = this.createProperties(properties);
  86. var oContent = {
  87. "b_action": "cognosViewer",
  88. "ui.action": "buxDropActiveReportOnCanvas",
  89. "ui.object": reportStoreID,
  90. "cv.responseFormat": "activeReport",
  91. "cv.id": this.getViewerId(),
  92. "bux": "true",
  93. "cv.buxCurrentUserRole": this.getUserRole()
  94. };
  95. if (this.getAttributeValue("savedOutputSearchPath") != null) {
  96. this.setSavedOutputSearchPath(this.getAttributeValue("savedOutputSearchPath"));
  97. oContent["ui.savedOutputSearchPath"] = this.getAttributeValue("savedOutputSearchPath");
  98. }
  99. if(this.isOpeningSavedDashboard()) {
  100. oContent["widget.openingSavedWidget"] = "true";
  101. var selectionFilterEnabled = this.getAttributeValue("selectionFilterEnabled");
  102. // For older workspaces default the value to true
  103. if (typeof selectionFilterEnabled == "undefined" || selectionFilterEnabled === null) {
  104. this.m_bSelectionFilterSwitch = true;
  105. }
  106. else {
  107. this.m_bSelectionFilterSwitch = selectionFilterEnabled == "true" ? true : false;
  108. }
  109. }
  110. this.iContext.iEvents.svc.addWire(this.iContext.widgetId, "com.ibm.bux.data.filterCache.init", "widgetBuxCanvasTabs", "com.ibm.bux.data.filterCache.init");
  111. this.postReport(oContent);
  112. },
  113. /*
  114. * Send server request to fetch active report saved ouput
  115. */
  116. postReport: function(content) {
  117. this.m_viewerLoadInitiated = true;
  118. if(content) {
  119. var args = {
  120. url: this.buildPostUrl(),
  121. sync: false,
  122. preventCache: true,
  123. content: content,
  124. error: dojo.hitch(this, function(response){
  125. this.fireEvent("com.ibm.bux.widget.render.done", null, {noAutoResize:true});
  126. this.fireEvent("com.ibm.bux.widget.notification", null, {type: "error", message: response.message, description: response.description});
  127. })
  128. };
  129. if (typeof xhrMultiPart !== "undefined" && xhrMultiPart.active) {
  130. args.load = dojo.hitch(this, function(response){
  131. this.loadContent(response.responseText);
  132. this.postLoadContent();
  133. });
  134. xhrMultiPart.Post(args);
  135. } else {
  136. args.load = dojo.hitch(this, function(response, ioArgs){
  137. var responseContentType = ioArgs.xhr.getResponseHeader("Content-Type");
  138. if (responseContentType!=null && responseContentType.indexOf("text/html") != -1 && response!=null&& response.match(/<ERROR_CODE>CAM_PASSPORT_ERROR<\/ERROR_CODE>/)!=null) {
  139. this.handlePassportErrorFromDispatcher();
  140. } else {
  141. this.loadContent(response);
  142. this.postLoadContent();
  143. }
  144. });
  145. dojo.xhrPost(args);
  146. }
  147. }
  148. },
  149. /*
  150. * A part of the postReport response handler:
  151. *
  152. * Sets callback functions on ActiveReport application
  153. * Disables extra generic event wirings for upgrade scenario
  154. */
  155. postLoadContent: function(){
  156. var bIsOpeningSavedDashboard = this.isOpeningSavedDashboard();
  157. this.iframe = dojo.byId(this.getIFrameId());
  158. if(this.iframe) {
  159. this.iframe.Application_OnLoad = dojo.hitch(this, "onActiveReportLoaded", bIsOpeningSavedDashboard);
  160. this.iframe.Application_OnBeforeLoad = dojo.hitch(this, "onActiveReportBeforeLoad");
  161. }
  162. if (bIsOpeningSavedDashboard && this._isWidgetPreCaspianVersion() ) {
  163. //Upgrade scenario - ensure not listening to new generic events (drill, slider, prompt)
  164. this._disableListenToNewlySupportedEvents();
  165. }
  166. this.hideLoading();
  167. if(dojo.isIos){
  168. //apply touch style for mobile
  169. //parent div of iframe
  170. var chromeDiv = this._getChromeObject()._pane;
  171. chromeDiv.setAttribute( "style", "overflow:auto; -webkit-overflow-scrolling:touch;" );
  172. //iframe
  173. this.iframe.setAttribute( "style", "-webkit-transform: translateZ(0px);" );
  174. }
  175. },
  176. /*
  177. * ACTIVE REPORT INTEGRATION POINT
  178. * onBeforeLoad handler that Active Report application calls before loading starts.
  179. */
  180. onActiveReportBeforeLoad: function()
  181. {
  182. this.hideLoading();
  183. },
  184. /*
  185. * ACTIVE REPORT INTEGRATION POINT
  186. * onLoaded handler that Active Report application calls once loading is completed.
  187. */
  188. onActiveReportLoaded: function(bOpeningSavedWidget)
  189. {
  190. var v_oFrameApp = this.getApplication();
  191. v_oFrameApp.SetChangeStateHandler(dojo.hitch(this, "onActiveReportStateChange"));
  192. this.m_isActiveReportOutputPreCaspianVersion = this._isActiveReportOutputPreCaspianVersion();
  193. this._getFilterableItems(); //populate Filterable items names
  194. if (bOpeningSavedWidget) {
  195. this._restoreSavedState(v_oFrameApp);
  196. } else {
  197. if (this.m_oCanvasContext) { //for onDrop behaviour
  198. if (this._hasFunctionProperty(v_oFrameApp, 'SetWidgetContext')) {
  199. v_oFrameApp.SetWidgetContext(this.m_oCanvasContext);
  200. }
  201. }
  202. }
  203. this.setupKeys();
  204. this._adjustWidgetDimension(v_oFrameApp, bOpeningSavedWidget);
  205. this._applicationLoaded();
  206. this.fireEvent("com.ibm.bux.widget.render.done", null, {hasIframe: true});
  207. this.hideLoading();
  208. },
  209. /*
  210. * Will invoke the callback:
  211. * (a) immediately if the underlying active report object is already loaded
  212. * (b) in the future, once the active report object has been loaded
  213. */
  214. _invokeWhenLoaded: function(fCallback) {
  215. if(!this.m_bApplicationLoaded && this.m_aWaitUntilLoadedQueue) {
  216. this.m_aWaitUntilLoadedQueue.push(fCallback);
  217. } else {
  218. fCallback.call();
  219. }
  220. },
  221. /*
  222. * Only call once, when the active report object is first loaded.
  223. * This will service the queue of functions and then clear it.
  224. */
  225. _applicationLoaded: function() {
  226. while(!this.m_bApplicationLoaded && this.m_aWaitUntilLoadedQueue.length) {
  227. var fCallback = this.m_aWaitUntilLoadedQueue.shift();
  228. if(fCallback) {
  229. fCallback.call();
  230. }
  231. }
  232. this.m_bApplicationLoaded = true;
  233. },
  234. /*
  235. * A part of ActiveReport post-load process
  236. * Adjust IFrame dimension once Active report is rendered
  237. */
  238. _adjustWidgetDimension: function (theApp, bOpeningSavedWidget) {
  239. // set the iframe dimensions
  240. var iframe = dojo.byId( this.getIFrameId());
  241. var appDimensions = null;
  242. if ( theApp && iframe ) {
  243. if (!bOpeningSavedWidget) {
  244. //make iframe size small
  245. iframe.style.width = "20px";
  246. iframe.style.height = "20px";
  247. }
  248. iframe.setAttribute("loadState","complete");
  249. //set iframe size to Active report size
  250. appDimensions = theApp.GetApplicationDimensions();
  251. iframe.style.width = appDimensions.width + "px";
  252. iframe.style.height = appDimensions.height + "px";
  253. //set chrome pane size to Active report size
  254. var v_oPane = this._getChromeObject()._pane;
  255. v_oPane.defaultH = appDimensions.height;
  256. v_oPane.defaultW = appDimensions.width;
  257. }
  258. if (appDimensions) {
  259. this.setReportContentDimensions(appDimensions.width, appDimensions.height);
  260. }
  261. },
  262. /**
  263. * A part of ActiveReport post-load process
  264. * Get saved state from property and apply to Active Report
  265. */
  266. _restoreSavedState: function (theApp) {
  267. //RESTORE SAVED STATE.
  268. var oSavedState = this.properties.getActiveReportState();
  269. if(oSavedState) {
  270. if (this._hasFunctionProperty(theApp, 'SetFullState')) {//if the api exists
  271. theApp.SetFullState(oSavedState);
  272. }
  273. }
  274. },
  275. setReportContentDimensions: function(width, height) {
  276. var nContent = dojo.byId(this.getContentId());
  277. if (nContent) {
  278. nContent.style.width = width + 'px';
  279. nContent.style.height = height + 'px';
  280. }
  281. },
  282. showLoading: function() {
  283. dojo.byId(this.getLoadingId()).style.display = "";
  284. //There is a bug in FF: When an iFrame is not displayed
  285. //(display: none), getComputedStyle() returns null. IROT
  286. //needs this API, so use visibility: hidden instead. See:
  287. //https://bugzilla.mozilla.org/show_bug.cgi?id=548397
  288. var nContent = dojo.byId(this.getContentId());
  289. nContent.style.position = "absolute";
  290. nContent.style.visibility = "hidden";
  291. //Set to minimum size to prevent scrollbars if the
  292. //content is larger than the container.
  293. this.m_sDivWidth = nContent.style.width;
  294. this.m_sDivHeight = nContent.style.height;
  295. nContent.style.width = "0px";
  296. nContent.style.height = "0px";
  297. },
  298. hideLoading: function() {
  299. var nContent = dojo.byId(this.getContentId());
  300. if (nContent) {
  301. nContent.style.position = "static";
  302. nContent.style.visibility = "visible"; //default
  303. if (this.m_sDivHeight && this.m_sDivWidth) {
  304. nContent.style.width = this.m_sDivWidth;
  305. nContent.style.height = this.m_sDivHeight;
  306. }
  307. }
  308. dojo.byId(this.getLoadingId()).style.display = "none";
  309. },
  310. /*
  311. * This function is called from RequestHandler.onFault method
  312. *
  313. * hideLoading method should be called to remove 'loading...'
  314. */
  315. postOnFault: function() {
  316. this.hideLoading();
  317. },
  318. /*
  319. * ACTIVE REPORT INTEGRATION POINT
  320. * onStateChange handler that Active Report application calls when public context is changed.
  321. */
  322. onActiveReportStateChange: function()
  323. {
  324. if (!this.m_bSelectionFilterSwitch) {
  325. return;
  326. }
  327. var oFrameApp = this.getApplication();
  328. if (!oFrameApp) {
  329. return;
  330. }
  331. var oStatePayload = null;
  332. if (this.m_isActiveReportOutputPreCaspianVersion) {
  333. if (this._hasFunctionProperty(oFrameApp, 'GetState')) { //Old API
  334. oStatePayload = oFrameApp.GetState();
  335. }
  336. } else {
  337. if (this._hasFunctionProperty(oFrameApp, 'GetWidgetContext')) {
  338. oStatePayload = oFrameApp.GetWidgetContext();
  339. this._convertRangeContext(oStatePayload, /*bFromActiveReportForGeneric*/ true);
  340. }
  341. }
  342. if (oStatePayload) {
  343. if (!oStatePayload.clientId) {
  344. oStatePayload.clientId = this.getWidgetId();
  345. }
  346. //append the secion below if discrete value exists
  347. if (this.m_oSelectionFilterBasePayload) {
  348. oStatePayload["com.ibm.widget.context.bux.selection"] = this.m_oSelectionFilterBasePayload;
  349. }
  350. this.fireEvent( "com.ibm.widget.contextChanged", null, oStatePayload);
  351. //Save the fact that this widget sent context changed event with something
  352. this.setSelectionFilterSent(true);
  353. }
  354. },
  355. broadcastSelectionFilter: function() {
  356. this.onActiveReportStateChange();
  357. },
  358. /*
  359. * When discrete public variable exist, m_oSelectionFilterBasePayload is an object with variable names.
  360. * return true if the field is not null
  361. */
  362. somethingSelected: function()
  363. {
  364. return (this.m_oSelectionFilterBasePayload)? true: false;
  365. },
  366. /*
  367. * Save widget
  368. */
  369. onWidgetSave: function(evt) {
  370. this.cleanSavedAttributes();
  371. //SAVE STATE
  372. var oFrameApp = this.getApplication();
  373. if (!oFrameApp) {
  374. this.fireEvent( "com.ibm.bux.widget.save.done", null, {'status':false});
  375. return;
  376. }
  377. if (this._hasFunctionProperty(oFrameApp, 'GetFullState')) {
  378. var oState = oFrameApp.GetFullState();
  379. if (oState) {
  380. this.properties.setActiveReportState(oState);
  381. }
  382. }
  383. this.updateSavedAttributes( "savedOutput" );
  384. this.fireEvent( "com.ibm.bux.widget.save.done", null, {'status':true});
  385. },
  386. /*
  387. * ACTIVE REPORT INTEGRATION POINT
  388. * handler of com.ibm.widget.contextChanged event
  389. */
  390. onOtherWidgetsContextChanged: function(evt) {
  391. var payload = evt.payload;
  392. var oFrameApp = this.getApplication();
  393. if (!oFrameApp) {
  394. return;
  395. }
  396. if (this.m_isActiveReportOutputPreCaspianVersion) {
  397. //Safe Guard for pre-Caspian active report output:
  398. //We check here if active report is pre-Caspian, then pass Array only if it is custom Array.
  399. if (this._isPayloadSupportedByPreCaspianActiveReport(payload)) {
  400. if (this._hasFunctionProperty(oFrameApp, 'SetState')) {
  401. oFrameApp.SetState(payload);
  402. }
  403. }
  404. } else {
  405. this.processSetWidgetContext(oFrameApp, payload);
  406. }
  407. },
  408. processSetWidgetContext: function(oApplication, genericPayload) {
  409. if (this.hasPublicVariables() && this._hasFunctionProperty(oApplication, 'SetWidgetContext')) {
  410. this.m_oWidgetContextManager.updateContextCollection(genericPayload);
  411. this.m_oCanvasContext = this.m_oWidgetContextManager.genMergedWidgetContextObject(this.m_oCanvasContextCollection);
  412. oApplication.SetWidgetContext(this.m_oCanvasContext);
  413. }
  414. },
  415. onUnload: function(evt) {
  416. var iframe = dojo.byId(this.getIFrameId());
  417. if (iframe) {
  418. dojo.destroy(iframe);
  419. }
  420. this.inherited(arguments);
  421. },
  422. onWidgetRefresh: function ( evt ){
  423. var refreshDonePayload = {};
  424. if (this.iframe) {
  425. var viewerObject = this.getViewerObject();
  426. if( evt && viewerObject){
  427. viewerObject.executeAction( "RefreshActiveReport" );
  428. }
  429. }
  430. this.fireEvent( "com.ibm.bux.widget.refresh.done", null, refreshDonePayload);
  431. },
  432. onWidgetResize: function(evt) {
  433. var iframe = dojo.byId(this.getIFrameId());
  434. if ( iframe ) {
  435. this.setReportContentDimensions(evt.payload.resize.w, evt.payload.resize.h);
  436. iframe.width = evt.payload.resize.w;
  437. iframe.height = evt.payload.resize.h;
  438. if ( iframe.style ) {
  439. iframe.style.width = evt.payload.resize.w + "px";
  440. iframe.style.height = evt.payload.resize.h + "px";
  441. }
  442. }
  443. },
  444. buildPostUrl: function () {
  445. return this.getAttributeValue("gateway");
  446. },
  447. isSavedOutput: function(){
  448. return false;
  449. },
  450. isSaveNecessary: function() {
  451. var sHasAlreadySaved = this.getAttributeValue("mostRecentSavedOutput");
  452. var sSavedOutputSearchPath = this.getAttributeValue("savedOutputSearchPath");
  453. return (sHasAlreadySaved === "true" || sSavedOutputSearchPath) ? false : true;
  454. },
  455. handleFault: function() {
  456. this.inherited(arguments);
  457. this.hideLoading();
  458. },
  459. setupKeys: function() {
  460. //Setup F10 and F12
  461. var doc = this.getIFrameDocument();
  462. if(doc) {
  463. dojo.connect(doc.body, "onkeypress", dojo.hitch(this, function(evt) {
  464. switch(evt.charOrCode) {
  465. case dojo.keys.F10:
  466. this.focusOnToolbar(evt);
  467. break;
  468. case dojo.keys.F12:
  469. if (evt.shiftKey) {
  470. this.focusOnPane(evt);
  471. }
  472. break;
  473. }
  474. }));
  475. }
  476. //Divs to redirect focus so it cycles forward and
  477. //backward through the active report
  478. this._makeInvisibleFocusDiv("before", "first"); //On F12, focus will be set to this node
  479. this._makeInvisibleFocusDiv("before", "last"); //On Shift+Tab, focus will be set to this node
  480. this._makeInvisibleFocusDiv("after", "first"); //On Tab, focus will be set to this node
  481. },
  482. _makeInvisibleFocusDiv: function(placePosition, focusPosition) {
  483. //Make an invisible, focusable div
  484. var div = dojo.create(
  485. "div",
  486. {
  487. tabIndex: 0,
  488. visibility: "hidden",
  489. position: "absolute"
  490. },
  491. this.iframe,
  492. placePosition
  493. );
  494. //When focus received, move it elsewhere.
  495. dojo.connect(div, "onfocus", dojo.hitch(this, function(){
  496. this.cycleFocus(focusPosition);
  497. }));
  498. },
  499. cycleFocus: function(position) {
  500. //Refocus to first or last element in iframe
  501. var tabElems = dijit._getTabNavigable(this.getIFrameDocument().body);
  502. var toFocus;
  503. if (position === "first") {
  504. toFocus = tabElems.lowest || tabElems.first;
  505. } else {
  506. toFocus = tabElems.highest || tabElems.last;
  507. }
  508. if (toFocus) {
  509. dijit.focus(toFocus);
  510. }
  511. },
  512. _getChromeObject: function() {
  513. var chromeObjectId = bux.IWidgetUtils.widgetIdToChromeId(this.iContext.widgetId);
  514. return bux.IWidgetUtils.getChromeById(chromeObjectId);
  515. },
  516. focusOnToolbar: function(evt) {
  517. var chromeObject = this._getChromeObject();
  518. if (chromeObject) {
  519. chromeObject._pane.focusToolbar(this.iframe);
  520. }
  521. if (dojo.isIE || dojo.isTrident) {
  522. evt.keyCode = 0;
  523. }
  524. dojo.stopEvent(evt);
  525. },
  526. focusOnPane: function(evt) {
  527. var chromeObject = this._getChromeObject();
  528. if (chromeObject) {
  529. chromeObject._pane._focusBorder();
  530. }
  531. dojo.stopEvent(evt);
  532. },
  533. /*
  534. * process incoming generic event
  535. * take values part from widget context and pass to the application as state
  536. */
  537. onGenericEvent: function(evt) {
  538. var oFrameApp = this.getApplication();
  539. if (!oFrameApp) {
  540. return;
  541. }
  542. if ( !this.m_isActiveReportOutputPreCaspianVersion ) {
  543. this.processSetWidgetContext(oFrameApp, evt.payload);
  544. }
  545. },
  546. /*
  547. * @override
  548. */
  549. createProperties: function(properties) {
  550. return new ActiveReportIWidgetProperties( this, properties );
  551. },
  552. temporaryStateCleanup: function(oState) {
  553. var oCleanState = {};
  554. if (oState && oState.variables) {
  555. var oVariables = oState.variables;
  556. for(var sName in oVariables) {
  557. var oValues = oVariables[sName];
  558. var aValues = [];
  559. for(var sValue in oValues) {
  560. if (typeof(oValues[sValue]) == 'string') {
  561. aValues.push(oValues[sValue]);
  562. }
  563. }
  564. if (aValues.length>0) {
  565. oCleanState[sName] = aValues;
  566. }
  567. }
  568. return {'variables': oCleanState};
  569. }
  570. return oState;
  571. },
  572. /*
  573. * returns true if saved version information is older than Caspian
  574. */
  575. _isWidgetPreCaspianVersion: function() {
  576. var sSavedVersion = this.getAttributeValue("version");
  577. return this._isOlderVersion(this.BUX_REPORT_VERSION, sSavedVersion);
  578. },
  579. _isOlderVersion: function(sBaseVersion, sTest) {
  580. if (!sBaseVersion || !sTest) {
  581. return true;
  582. }
  583. return (sBaseVersion > sTest);
  584. },
  585. /*
  586. * In Casipan, generic form of prompt/drill/selectValueControl events are implemented
  587. * We want these events to be disabled when pre-Caspian workspace is open so that
  588. * it does not react to them. This is to provide same behaivour.
  589. *
  590. * Also, turn off getItems/getValues filter events so that
  591. * slider configuration dialogs do not show items from it.
  592. */
  593. _disableListenToNewlySupportedEvents: function() {
  594. var payload = {};
  595. payload[ '*' ] = { blockedEvents:[
  596. this.m_oWidgetContextManager.EVENT_NAME_PROMPT,
  597. this.m_oWidgetContextManager.EVENT_NAME_DRILL,
  598. this.m_oWidgetContextManager.EVENT_NAME_SELECTVALUECONTROL,
  599. this.EVENT_NAME_FILTER_ITEMS_GET,
  600. this.EVENT_NAME_FILTER_VALUES_GET
  601. ]
  602. };
  603. this.fireEvent("com.ibm.bux.widget.updateEventFilter", null, payload);
  604. },
  605. /*
  606. * returns true if the active report version is smaller than current ACTIVEREPORT_VERSION
  607. */
  608. _isActiveReportOutputPreCaspianVersion: function() {
  609. var oFrameApp = this.getApplication();
  610. if (!oFrameApp) {
  611. return null;
  612. }
  613. var sVersion = '0';
  614. if ( this._hasFunctionProperty(oFrameApp, 'GetOutputVersion')) {
  615. sVersion = oFrameApp.GetOutputVersion();
  616. this.m_sActiveReportOutputVersion = sVersion;
  617. }
  618. return this._isOlderVersion(/* base */ this.ACTIVEREPORT_VERSION, /* toCompare */ sVersion);
  619. },
  620. /*
  621. * returns m_sActiveReportOutputVersion
  622. */
  623. getActiveReportOutputVersion: function() {
  624. return this.m_sActiveReportOutputVersion;
  625. },
  626. /*
  627. * returns m_sActiveReportOutputVersion
  628. */
  629. getPublicVariableNames: function() {
  630. return this.m_oPublicVariableNames || {};
  631. },
  632. /*
  633. * pre-Caspian active report in SetState and GetState functions use custom Array object whose custome functions.
  634. * When regular Array object is passed to it, it errors out and becomes static.
  635. * This function determins if payload can be supported by pre-Caspian active report
  636. *
  637. * return true if Array object has any custom function
  638. */
  639. _isPayloadSupportedByPreCaspianActiveReport: function(oPayload) {
  640. for (var sPropertyName in oPayload) {
  641. var oNameValuePairObject = oPayload[sPropertyName];
  642. for (var sName in oNameValuePairObject) {
  643. var oValue = oNameValuePairObject[sName];
  644. if (typeof(oValue) == 'object') {
  645. for (var sArrayPropertyName in oValue) {
  646. if (typeof(oValue[sArrayPropertyName]) == 'function') {
  647. return true;
  648. }
  649. }
  650. }
  651. }
  652. }
  653. return false;
  654. },
  655. /*
  656. * Returns true if passed object has a function with name of passed functionName
  657. */
  658. _hasFunctionProperty:function(obj, functionName) {
  659. if (obj && functionName) {
  660. if (obj[functionName] && typeof obj[functionName] == 'function') {
  661. return true;
  662. }
  663. }
  664. return false;
  665. },
  666. /*
  667. * Generic event uses Arrays for range values. One range can have many min/max values in generic event.
  668. * However, Active report range variables have one min/max value as an object.
  669. *
  670. * This function masages range value type to make them compatible.
  671. *
  672. * if bFromActiveReportForGeneric is true, puts range value into an array
  673. * else, takes first item from array and set as value
  674. */
  675. _convertRangeContext:function(oActiveReportContext, bFromActiveReportForGeneric) {
  676. var oWidgetContext = oActiveReportContext[this.m_oWidgetContextManager.PP_WIDGET_CONTEXT];
  677. if (oWidgetContext) {
  678. var oRanges = oWidgetContext[this.m_oWidgetContextManager.PP_RANGES];
  679. if (oRanges) {
  680. var newRanges = {};
  681. for (var sName in oRanges) {
  682. var value = oRanges[sName];
  683. if (bFromActiveReportForGeneric) {
  684. //PUT INTO an Array
  685. newRanges[sName] = [value];
  686. } else {
  687. //Pass first item as Active report takes only one range input.
  688. if (value && value.length>0) {
  689. newRanges[sName] = value[0];
  690. }
  691. }
  692. }
  693. oWidgetContext[this.m_oWidgetContextManager.PP_RANGES] = newRanges;
  694. }
  695. }
  696. },
  697. /*
  698. * onGetFilterableItems
  699. */
  700. onGetFilterableItems: function(evt) {
  701. var oFrameApp = this.getApplication();
  702. if (!oFrameApp) {
  703. this.fireEvent('com.ibm.bux.filter.items.get.done', null, {});
  704. return;
  705. }
  706. var aItems = this._getFilterableItems();
  707. var payload = {
  708. 'invisible' : [],
  709. 'visible' : aItems
  710. };
  711. this.fireEvent('com.ibm.bux.filter.items.get.done', null, payload);
  712. },
  713. _getFilterableItems: function() {
  714. var aItems = [];
  715. var oFrameApp = this.getApplication();
  716. if (!oFrameApp) {
  717. return aItems;//Shouldn't be here
  718. }
  719. this.m_oPublicVariableNames = this.m_oPublicVariableNames || {};
  720. var hasDiscriteValues = false;
  721. if (this._hasFunctionProperty(oFrameApp, 'GetDiscreteVariables')) {//if the api exists
  722. var aDiscreteVariables = [].concat(oFrameApp.GetDiscreteVariables()); //convert returned object to standard array
  723. for (var idx in aDiscreteVariables) {
  724. aItems.push( this._genFilterableItemObject( aDiscreteVariables[idx], /*isRange*/false) );
  725. this.m_oPublicVariableNames[aDiscreteVariables[idx]] = 'D';//DISCRETE
  726. hasDiscriteValues = true;
  727. }
  728. }
  729. if (this._hasFunctionProperty(oFrameApp, 'GetRanges')) {//if the api exists
  730. var aRanges = [].concat(oFrameApp.GetRanges()); //convert returned object to standard array
  731. for (var idx in aRanges) {
  732. aItems.push( this._genFilterableItemObject( aRanges[idx], /*isRange*/true) );
  733. this.m_oPublicVariableNames[aRanges[idx]] = 'R'; //range
  734. }
  735. }
  736. if (hasDiscriteValues) {
  737. this.m_oSelectionFilterBasePayload = {
  738. "selection":{
  739. "id":this.getWidgetId(),
  740. "valueType":"string"
  741. }
  742. };
  743. }
  744. return aItems;
  745. },
  746. /*
  747. * returns true if m_oPublicVariableNames field is not an empty object
  748. */
  749. hasPublicVariables: function() {
  750. var found = false;
  751. for(var name in this.m_oPublicVariableNames) {
  752. found = true;
  753. break;
  754. }
  755. return found;
  756. },
  757. /*
  758. * returns an object whoes label, name and optional range properties.
  759. */
  760. _genFilterableItemObject: function (sItemName, /*isRange*/ isRange) {
  761. var object = {
  762. 'label' : sItemName,
  763. 'name' : sItemName
  764. };
  765. if (isRange) {
  766. object['range'] = true;
  767. }
  768. return object;
  769. },
  770. onGetFilterValues: function(evt) {
  771. var oItem = evt.payload.payload;
  772. var sName = oItem.name;
  773. var oPayload = {name: sName};
  774. if (!evt.payload || !evt.payload.payload) {
  775. this.fireEvent(this.EVENT_NAME_FILTER_VALUES_GET_DONE, null, oPayload);
  776. return;
  777. }
  778. //The remainder of this logic requires the active report object be loaded.
  779. this._invokeWhenLoaded(dojo.hitch(this, function() {
  780. //Ensure filterable items have been loaded
  781. if(!this.m_oPublicVariableNames) {
  782. this._getFilterableItems();
  783. }
  784. if (!this.m_oPublicVariableNames[sName]) {
  785. this.fireEvent(this.EVENT_NAME_FILTER_VALUES_GET_DONE, null, oPayload);
  786. return;
  787. }
  788. var oFrameApp = this.getApplication();
  789. var aNewValues = [];
  790. try {
  791. if (this.m_oPublicVariableNames[sName] === 'R') {
  792. //i.e. a range
  793. if (this._hasFunctionProperty(oFrameApp, 'GetRangeValues')) {//if the api exists
  794. var oRange = oFrameApp.GetRangeValues(sName);
  795. var newObj = {'max': null, 'min': null};
  796. if (typeof oRange.min != 'undefined' && typeof oRange.max != 'undefined') {
  797. newObj.min = parseFloat(oRange.min);
  798. newObj.max = parseFloat(oRange.max);
  799. }
  800. oPayload.range = newObj;
  801. }
  802. } else if (this.m_oPublicVariableNames[sName] === 'D') {
  803. //i.e. discrete values
  804. if (this._hasFunctionProperty(oFrameApp, 'GetValuesForDiscreteVariable')) {//if the api exists
  805. var aValues = [].concat(oFrameApp.GetValuesForDiscreteVariable(sName)); //convert returned object to standard array
  806. if (aValues && aValues.length>0) {
  807. for (var idx in aValues) {
  808. aNewValues.push(
  809. {'mun': 'unknown', //TODO - remove mun
  810. 'caption': aValues[idx]}
  811. );
  812. }
  813. }
  814. oPayload.values = aNewValues;
  815. }
  816. }
  817. } catch (e) {
  818. throw e; //Throw for AR until root cause is fixed in AR side
  819. } finally {
  820. oPayload.modelInfo = { 'path': 'unknow_' + this.getWidgetId() };
  821. this.fireEvent(this.EVENT_NAME_FILTER_VALUES_GET_DONE, null, oPayload);
  822. }
  823. }));
  824. },
  825. onWidgetShow: function(evt) {
  826. /**
  827. * Issue with Active Reports displaying a visualization in IE8. We need to force the Active Report to redraw the first time it's made visible
  828. */
  829. if(this.getViewerObject().getAdvancedServerProperty("VIEWER_JS_RELOAD_AR_IE8") === "true" && evt.payload.isVisible && !this.m_bActiveReportRedrawn && dojo.isIE == 8) {
  830. this.m_bActiveReportRedrawn = true;
  831. var sBackupSrc = this.iframe.src;
  832. this.iframe.src=""; //Testing shows this is necessary;
  833. this.iframe.src = sBackupSrc;
  834. }
  835. },
  836. /**
  837. * @override
  838. */
  839. reselectSelectionFilterObjects: function() {
  840. var value = this.getAttributeValue( "selectionFilterSent" );
  841. this.setSelectionFilterSent(value === "true");
  842. this.removeAttributeValue("selectionFilterSent");
  843. },
  844. /*
  845. * Override
  846. */
  847. updateSavedAttributes: function(attribType) {
  848. this.inherited(arguments);
  849. if (this.selectionFilterSent()) {
  850. this.setAttributeValue( "selectionFilterSent", "true" );
  851. }
  852. },
  853. /*
  854. * Override
  855. */
  856. cleanSavedAttributes: function() {
  857. this.inherited(arguments);
  858. this.removeAttributeValue("selectionFilterSent");
  859. },
  860. /*
  861. * This event handler populates canvas the filter data.
  862. *
  863. * Open workspace scenario, viewer widgets and slider widgets send their filter context to Canvas.
  864. * Active report must listen to the event and populate contextCollection with it.
  865. *
  866. * This is neccessary to support deleting/resetting filter request from other widget.
  867. * Before delete filter, it searches source widgetId in contextCollection to determine whether the request is relevant or not.
  868. */
  869. updateFilterCache: function(iEvent){
  870. this.m_oWidgetContextManager.updateContextCollection(iEvent.payload);
  871. },
  872. /*
  873. * Handler of 'com.ibm.widget.context.get' event
  874. */
  875. onGetWidgetContext: function(iEvent) {
  876. var payload = {};
  877. if (this.iframe && this.isSelectionFilterEnabled()) {
  878. var oFrameApp = this.getApplication();
  879. if (this._hasFunctionProperty(oFrameApp, 'GetWidgetContext')) {
  880. payload = oFrameApp.GetWidgetContext();
  881. payload.clientId = this.getWidgetId();
  882. }
  883. }
  884. this.fireEvent( 'com.ibm.widget.context.get.done', null , payload);
  885. },
  886. /*
  887. * Handler of com.ibm.bux.canvas.context.get.done event
  888. *
  889. * Saves canvas context into its property(m_oCanvasContext).
  890. * Then once ActiveReport content is loaded,
  891. * onActiveReportLoaded function calls Active report SetWidgetContext api the context.
  892. */
  893. onGetCanvasContextDone: function(evt) {
  894. var aPayload = evt.payload;
  895. for(var i=0; i<aPayload.length; i++ ) {
  896. this.m_oWidgetContextManager.updateContextCollection(aPayload[i]);
  897. }
  898. this.m_oCanvasContext = this.m_oWidgetContextManager.genMergedWidgetContextObject();
  899. },
  900. /*
  901. * Temporary debug logging for integration test with IROT dev team
  902. * This will be removed after integration testing is complete.
  903. */
  904. DEBUG_LOG: function(msg, obj) {
  905. if (this.isDebugMode()) {
  906. if (console) {
  907. if (msg && obj) {
  908. console.log("%s %o", msg, obj);
  909. } else if (msg){
  910. console.log(msg);
  911. } else if (obj) {
  912. console.log(obj);
  913. }
  914. }
  915. }
  916. },
  917. /*
  918. * This function name with typo was release in RP1.
  919. * This function must stay for the case of RP1 deployment on Caspian release.
  920. */
  921. DEUBG_LOG: function(msg, obj) {
  922. this.DEBUG_LOG(msg,obj);
  923. },
  924. isDebugMode: function() {
  925. return (dojo && dojo['config'] && dojo['config']['isDebug']);
  926. }
  927. });