cvcalculations.js 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911
  1. /*
  2. *+------------------------------------------------------------------------+
  3. *| Licensed Materials - Property of IBM
  4. *| IBM Cognos Products: Viewer
  5. *| (C) Copyright IBM Corp. 2001, 2011
  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. /**
  13. * CognosViewerCalculation constructor (base class for all calculation rules)
  14. * @constructor
  15. */
  16. function CognosViewerCalculation() {
  17. this.m_oCV = null;
  18. }
  19. /**
  20. * Sets the cognos viewer object (called by the action factory
  21. * @param CCognosViewer object
  22. * @private
  23. */
  24. CognosViewerCalculation.prototype.setCognosViewer = function(oCV) {
  25. this.m_oCV = oCV;
  26. };
  27. /**
  28. * Returns an instance to the cognos viewer object
  29. * @return CCognosViewer object
  30. */
  31. CognosViewerCalculation.prototype.getCognosViewer = function() {
  32. return this.m_oCV;
  33. };
  34. /**
  35. * Most calculations require only 2 selected cells
  36. */
  37. CognosViewerCalculation.prototype.validSelectionLength = function(selectionController) {
  38. try {
  39. return selectionController.getAllSelectedObjects().length > 0;
  40. } catch (e) {
  41. return false;
  42. }
  43. };
  44. /**
  45. * Gets the display value to show in the calculation string. If the current selection is a column title, then
  46. * simply use the display from the selection, if not then find the defining cells display value
  47. */
  48. CognosViewerCalculation.prototype.getDisplayValueFromSelection = function(selection) {
  49. var displayValue = "";
  50. if (!selection) {
  51. return displayValue;
  52. }
  53. if (selection.getLayoutType() == "columnTitle") {
  54. displayValue = selection.getDisplayValues()[0];
  55. } else if (selection.getLayoutType() == "datavalue") {
  56. // only time we'd be doing a calculation and wouldn't have columnTitles selected
  57. // is in a list, so get the column header
  58. var viewerAction = this.m_oCV.getAction("CognosViewer");
  59. var selectionController = this.m_oCV.getSelectionController();
  60. var containerId = viewerAction.getContainerId(selectionController);
  61. displayValue = selection.getDataItemDisplayValue(viewerAction.getReportInfo(containerId));
  62. }
  63. if (displayValue.indexOf("+") != -1 || displayValue.indexOf("-") != -1 || displayValue.indexOf("*") != -1 || displayValue.indexOf("/") != -1) {
  64. displayValue = "(" + displayValue + ")";
  65. }
  66. return displayValue;
  67. };
  68. /**
  69. * Need to override this method if your class uses the CognosViewerCalculation getMenuItemString method
  70. * +, -, *, /
  71. */
  72. CognosViewerCalculation.prototype.getCalcSymbol = function() {};
  73. /**
  74. * Generates the menu item string to be displayed in the context menu. Used for simply calculations like
  75. * +, -, *, /
  76. */
  77. CognosViewerCalculation.prototype.getMenuItemString = function(menuEnabled) {
  78. var cognosViewer = this.getCognosViewer();
  79. var selectionController = cognosViewer.getSelectionController();
  80. var sMenuItemString = "";
  81. var selection, index;
  82. if (menuEnabled) {
  83. try {
  84. var selectionLength = selectionController.getAllSelectedObjects().length;
  85. if (selectionLength == 1) {
  86. selection = selectionController.getAllSelectedObjects()[0];
  87. if(this.m_bFlipSelection) {
  88. sMenuItemString = RV_RES.IDS_JS_CALCULATE_NUMBER + " " + this.getCalcSymbol() + " " + this.getDisplayValueFromSelection(selection);
  89. } else {
  90. sMenuItemString = this.getDisplayValueFromSelection(selection) + " " + this.getCalcSymbol() + " " + RV_RES.IDS_JS_CALCULATE_NUMBER;
  91. }
  92. } else {
  93. if (this.m_bFlipSelection) {
  94. selectionLength--;
  95. for (index=selectionLength; index >= 0; index--) {
  96. selection = selectionController.getAllSelectedObjects()[index];
  97. if (index != selectionLength) {
  98. sMenuItemString += " " + this.getCalcSymbol() + " ";
  99. }
  100. sMenuItemString += this.getDisplayValueFromSelection(selection);
  101. }
  102. }
  103. else {
  104. for (index=0; index < selectionLength; index++) {
  105. selection = selectionController.getAllSelectedObjects()[index];
  106. if (index > 0) {
  107. sMenuItemString += " " + this.getCalcSymbol() + " ";
  108. }
  109. sMenuItemString += this.getDisplayValueFromSelection(selection);
  110. }
  111. }
  112. }
  113. } catch (e) {
  114. sMenuItemString = this.getCalcSymbol();
  115. }
  116. } else {
  117. sMenuItemString = this.getCalcSymbol();
  118. }
  119. return sMenuItemString;
  120. };
  121. /**
  122. * Percent Difference Calculation
  123. */
  124. function PercentDifferenceCalculation() {}
  125. PercentDifferenceCalculation.prototype = new CognosViewerCalculation();
  126. PercentDifferenceCalculation.prototype.validSelectionLength = function(selectionController) {
  127. try {
  128. return selectionController.getAllSelectedObjects().length == 2;
  129. } catch (e) {
  130. return false;
  131. }
  132. };
  133. /**
  134. * Generates the menu item string to be displayed in the context menu
  135. */
  136. PercentDifferenceCalculation.prototype.getMenuItemString = function(menuEnabled) {
  137. var selectionController = this.getCognosViewer().getSelectionController();
  138. var sMenuItemString = RV_RES.IDS_JS_CALCULATE_PERCENT_DIFFERENCE;
  139. if (menuEnabled) {
  140. try {
  141. var selectionLength = selectionController.getAllSelectedObjects().length;
  142. sMenuItemString += " (";
  143. for (var index=0; index < selectionLength; index++) {
  144. var selection = selectionController.getAllSelectedObjects()[index];
  145. if (index > 0) {
  146. sMenuItemString += ", ";
  147. }
  148. sMenuItemString += this.getDisplayValueFromSelection(selection);
  149. }
  150. sMenuItemString += ")";
  151. } catch (e) {}
  152. }
  153. return sMenuItemString;
  154. };
  155. /**
  156. * Percent Difference Calculation
  157. */
  158. function PercentDifferenceCalculationSwapOrder()
  159. {
  160. this.m_bFlipSelection = true;
  161. }
  162. PercentDifferenceCalculationSwapOrder.prototype = new PercentDifferenceCalculation();
  163. /**
  164. * Generates the menu item string to be displayed in the context menu
  165. */
  166. PercentDifferenceCalculationSwapOrder.prototype.getMenuItemString = function(menuEnabled) {
  167. var selectionController = this.getCognosViewer().getSelectionController();
  168. var sMenuItemString = RV_RES.IDS_JS_CALCULATE_PERCENT_DIFFERENCE;
  169. if (menuEnabled) {
  170. try {
  171. var selectionLength = selectionController.getAllSelectedObjects().length;
  172. sMenuItemString += " (";
  173. selectionLength--;
  174. for (var index=selectionLength; index >= 0; index--) {
  175. var selection = selectionController.getAllSelectedObjects()[index];
  176. if (index < selectionLength) {
  177. sMenuItemString += ", ";
  178. }
  179. sMenuItemString += this.getDisplayValueFromSelection(selection);
  180. }
  181. sMenuItemString += ")";
  182. } catch (e) {}
  183. }
  184. return sMenuItemString;
  185. };
  186. /**
  187. * Addition calculation
  188. */
  189. function AdditionCalculation() {}
  190. AdditionCalculation.prototype = new CognosViewerCalculation();
  191. AdditionCalculation.prototype.getCalcSymbol = function() {
  192. return "+";
  193. };
  194. /**
  195. * Subtraction calculation
  196. */
  197. function SubtractionCalculation() {}
  198. SubtractionCalculation.prototype = new CognosViewerCalculation();
  199. SubtractionCalculation.prototype.getCalcSymbol = function() {
  200. return "-";
  201. };
  202. /**
  203. * Override the validSelectionLength method since additions allows from 1 to 2 selections
  204. */
  205. SubtractionCalculation.prototype.validSelectionLength = function(selectionController) {
  206. try {
  207. var selLength = selectionController.getAllSelectedObjects().length;
  208. return selLength > 0 && selLength < 3;
  209. } catch (e) {
  210. return false;
  211. }
  212. };
  213. /**
  214. * Subtraction calculation when we flip the selection order
  215. */
  216. function SubtractionCalculationSwapOrder()
  217. {
  218. this.m_bFlipSelection = true;
  219. }
  220. SubtractionCalculationSwapOrder.prototype = new SubtractionCalculation();
  221. /**
  222. * Multiplication calculation
  223. */
  224. function MultiplicationCalculation() {}
  225. MultiplicationCalculation.prototype = new CognosViewerCalculation();
  226. MultiplicationCalculation.prototype.getCalcSymbol = function() {
  227. return "*";
  228. };
  229. /**
  230. * Division Calculation
  231. */
  232. function DivisionCalculation() {}
  233. DivisionCalculation.prototype = new CognosViewerCalculation();
  234. DivisionCalculation.prototype.getCalcSymbol = function() {
  235. return "/";
  236. };
  237. DivisionCalculation.prototype.validSelectionLength = function(selectionController) {
  238. try {
  239. var selectionLength = selectionController.getAllSelectedObjects().length;
  240. return (selectionLength > 0 && selectionLength < 3);
  241. } catch (e) {
  242. return false;
  243. }
  244. };
  245. /**
  246. * Division Calculation when we swap the order of selection
  247. */
  248. function DivisionCalculationSwapOrder()
  249. {
  250. this.m_bFlipSelection = true;
  251. }
  252. DivisionCalculationSwapOrder.prototype = new DivisionCalculation();
  253. /**
  254. * Calculation Actions (Addition, Subtraction, Multiplication, Division, PercentDifference etc.)
  255. */
  256. function CalculationAction()
  257. {
  258. this.m_payload = "";
  259. this.m_menuBuilderClass = null;
  260. this.m_defaultName = "";
  261. this.m_constant = null;
  262. }
  263. CalculationAction.prototype = new ModifyReportAction();
  264. CalculationAction.prototype.getUndoHint = function()
  265. {
  266. return RV_RES.IDS_JS_CALCULATION;
  267. };
  268. CalculationAction.prototype.keepRAPCache = function()
  269. {
  270. return false;
  271. };
  272. /**
  273. * Specific rules for lists:
  274. * 1. No two selections can be on the same column.
  275. * 2. Selections have calculation Metadata
  276. * @return true if the current selections are valid for calculations
  277. */
  278. CalculationAction.prototype.listRules = function() {
  279. var selectionController = this.getCognosViewer().getSelectionController();
  280. var aSelectionObjects = selectionController.getSelections();
  281. if (aSelectionObjects.length > 1)
  282. {
  283. var tmp = {};
  284. for (var i = 0; i < aSelectionObjects.length; ++i)
  285. {
  286. var columnRef = aSelectionObjects[i].getColumnRef();
  287. if (typeof tmp[columnRef] == "undefined")
  288. {
  289. tmp[columnRef] = 1;
  290. }
  291. else
  292. {
  293. return false; //duplicate found
  294. }
  295. }
  296. }
  297. return selectionController.selectionsHaveCalculationMetadata();
  298. };
  299. /**
  300. * Specific rules for crosstabs
  301. * @return true if the current selections are valid for calculations
  302. */
  303. CalculationAction.prototype.crosstabRules = function() {
  304. var selectionController = this.getCognosViewer().getSelectionController();
  305. if (!selectionController.areSelectionsColumnRowTitles()) {
  306. return false;
  307. }
  308. if (selectionController.isRelational()) {
  309. if (!this.relationalCrosstabRules(selectionController)) {
  310. return false;
  311. }
  312. } else {
  313. if (!this.olapCrosstabRules(selectionController)) {
  314. return false;
  315. }
  316. }
  317. return true;
  318. };
  319. /**
  320. * Specific rules for relational data
  321. * @return true is the selections meet all the relational crosstab specific rules for allowing calculations
  322. */
  323. CalculationAction.prototype.relationalCrosstabRules = function(selectionController) {
  324. return selectionController.selectionsHaveCalculationMetadata();
  325. };
  326. /**
  327. * Specific rules for OLAP data
  328. * @return true if the selections meet all the olap specific crosstab rules for allowing calculations
  329. */
  330. CalculationAction.prototype.olapCrosstabRules = function(selectionController) {
  331. if (! selectionController.selectionsHaveCalculationMetadata())
  332. {
  333. return false;
  334. }
  335. if (!this.sameDimension(selectionController))
  336. {
  337. // Allow calculations between measures of different measure dimensions
  338. // Only allow members calcs if all measures
  339. return (typeof this.m_oCV.aQoSFunctions != "undefined") && this.m_oCV.aQoSFunctions.toString().indexOf('MULTIPLE_MEASURE_DIMENSION_CALCULATIONS') != -1 && selectionController.selectionsAreMeasures();
  340. }
  341. else
  342. {
  343. if (this.sameHierarchy(selectionController))
  344. {
  345. return true;
  346. }
  347. else
  348. {
  349. return (typeof this.m_oCV.aQoSFunctions != "undefined") && this.m_oCV.aQoSFunctions.toString().indexOf('VALUE_EXPRESSIONS_REF_MULTIPLE_HIERARCHIES_OF_SAME_DIMENSION') != -1;
  350. }
  351. }
  352. };
  353. /**
  354. * Checks to see if the selected cells are from the same hierarchy
  355. * @return true if the selections are from the same hierarchy, false otherwise
  356. */
  357. CalculationAction.prototype.sameDimension = function(selectionController) {
  358. try {
  359. var dim = "";
  360. var selLength = selectionController.getAllSelectedObjects().length;
  361. for (var selIndex = 0; selIndex < selLength; selIndex++) {
  362. if (dim.length == 0) {
  363. dim = selectionController.getAllSelectedObjects()[selIndex].getDimensionalItems('dun')[0][0];
  364. } else if (dim != selectionController.getAllSelectedObjects()[selIndex].getDimensionalItems('dun')[0][0]){
  365. return false;
  366. }
  367. }
  368. return true;
  369. }catch (e) {
  370. return false;
  371. }
  372. };
  373. CalculationAction.prototype.sameHierarchy = function(selectionController) {
  374. try {
  375. var dim = "";
  376. var selLength = selectionController.getAllSelectedObjects().length;
  377. for (var selIndex = 0; selIndex < selLength; selIndex++) {
  378. if (dim.length == 0) {
  379. dim = selectionController.getAllSelectedObjects()[selIndex].getDimensionalItems('hun')[0][0];
  380. } else if (dim != selectionController.getAllSelectedObjects()[selIndex].getDimensionalItems('hun')[0][0]){
  381. return false;
  382. }
  383. }
  384. return true;
  385. }catch (e) {
  386. return false;
  387. }
  388. };
  389. /**
  390. * For calculations, pass the calculation string to the RAP for generating calculation column name.
  391. */
  392. CalculationAction.prototype.addActionContextAdditionalParms = function()
  393. {
  394. var additionalContextParms = "";
  395. if(this.m_constant != null)
  396. {
  397. additionalContextParms += "<constant>" + xml_encode(this.m_constant) + "</constant>";
  398. if(this.m_swapSelectionOrder)
  399. {
  400. additionalContextParms += "<constantFirst/>";
  401. }
  402. }
  403. if(this.m_defaultName != "")
  404. {
  405. additionalContextParms += "<columnName>" + xml_encode(this.m_defaultName) + "</columnName>";
  406. }
  407. return additionalContextParms;
  408. };
  409. CalculationAction.prototype.setRequestParms = function(parms)
  410. {
  411. if(parms != null)
  412. {
  413. if(typeof parms.constant != null)
  414. {
  415. this.m_constant = parms.constant;
  416. }
  417. }
  418. };
  419. CalculationAction.prototype.buildDefaultName = function()
  420. {
  421. try {
  422. var calc = this.getCognosViewer().getCalculation(this.m_menuBuilderClass);
  423. this.m_defaultName = calc.getMenuItemString(true);
  424. if(this.m_constant != null)
  425. {
  426. var numberLabel = "" + this.m_constant;
  427. var separator = this.getCognosViewer().envParams['contentDecimalSeparator'];
  428. if (typeof separator != "undefined" && separator != null && separator != ".")
  429. {
  430. numberLabel = numberLabel.replace(".", separator);
  431. }
  432. this.m_defaultName = this.m_defaultName.replace(RV_RES.IDS_JS_CALCULATE_NUMBER, numberLabel);
  433. }
  434. } catch (e) {
  435. this.m_defaultName = "";
  436. }
  437. };
  438. CalculationAction.prototype.preProcess = function()
  439. {
  440. var selectionCount = this.getNumberOfSelections();
  441. this.buildDefaultName();
  442. if(this.m_swapSelectionOrder && selectionCount == 2)
  443. {
  444. var selectionController = this.getCognosViewer().getSelectionController();
  445. var sel1 = selectionController.getAllSelectedObjects()[0];
  446. var sel2 = selectionController.getAllSelectedObjects()[1];
  447. selectionController.m_aSelectedObjects = [sel2, sel1];
  448. }
  449. };
  450. CalculationAction.prototype.isFactCellOnCrosstabOrEmpty = function()
  451. {
  452. var selectionController = this.m_oCV.getSelectionController();
  453. var selectedObjects = selectionController.getAllSelectedObjects();
  454. if (selectedObjects != null && typeof selectedObjects != "undefined") {
  455. if (selectedObjects.length == 0) {
  456. return true;
  457. } else {
  458. var selectedObject = selectedObjects[0];
  459. //If the select object should be disabled when the user selects a fact cell(s).
  460. if (selectionController.getDataContainerType() == "crosstab" && selectedObject.getLayoutType() == 'datavalue')
  461. {
  462. return true;
  463. }
  464. }
  465. }
  466. return false;
  467. };
  468. CalculationAction.prototype.isSummaryOrAggregateCell = function()
  469. {
  470. var selectionController = this.m_oCV.getSelectionController();
  471. var selectedObjects = selectionController.getAllSelectedObjects();
  472. if (selectedObjects != null && typeof selectedObjects != "undefined") {
  473. var cellRef;
  474. var reCrosstabLevel = /\b(ol|il)\b/;
  475. for (var i = 0; i < selectedObjects.length; i++)
  476. {
  477. cellRef = selectedObjects[i].getCellRef();
  478. if (cellRef != null && typeof cellRef != "undefined") {
  479. if (selectedObjects[i].getLayoutType() == "summary" || (cellRef != null && reCrosstabLevel.test(cellRef.className)))
  480. {
  481. return true;
  482. }
  483. }
  484. cellRef =null;
  485. }
  486. }
  487. return false;
  488. };
  489. CalculationAction.prototype.isLastSelectionSingleDimensionNested = function()
  490. {
  491. var selectionController = this.m_oCV.getSelectionController();
  492. var selectedObjects = selectionController.getAllSelectedObjects();
  493. if (selectedObjects != null && typeof selectedObjects != "undefined" && selectedObjects.length) {
  494. var lastSelection = selectedObjects[selectedObjects.length - 1];
  495. var dimItemsAxis0 = lastSelection.getDimensionalItems('dun')[0];
  496. //If dimension of this item is same as any of its parents, its SD nested.
  497. if (dimItemsAxis0 && dimItemsAxis0.length && dimItemsAxis0[0]) {
  498. for(var parent=1; parent<dimItemsAxis0.length; ++parent) {
  499. if (dimItemsAxis0[parent]===dimItemsAxis0[0]) {
  500. return true;
  501. }
  502. }
  503. }
  504. }
  505. return false;
  506. };
  507. /**
  508. * Checks to see if all types of calculation are possible. This function
  509. * checks general conditions of selections that apply to all types of calculation.
  510. */
  511. CalculationAction.prototype.areCalculationsPossible = function()
  512. {
  513. var selectionController = this.getCognosViewer().getSelectionController();
  514. if(this.isFactCellOnCrosstabOrEmpty())
  515. {
  516. return false;
  517. }
  518. if(this.isSelectionOnChart())
  519. {
  520. return false;
  521. }
  522. if(this.isSummaryOrAggregateCell())
  523. {
  524. return false;
  525. }
  526. if (!selectionController.selectionsInSameDataContainer())
  527. {
  528. return false;
  529. }
  530. // different rules for lists and crosstabs
  531. if (selectionController.getDataContainerType() == "list")
  532. {
  533. return this.listRules(selectionController);
  534. }
  535. else if (selectionController.getDataContainerType() == "crosstab" && ! this.isLastSelectionSingleDimensionNested())
  536. {
  537. return this.crosstabRules(selectionController);
  538. }
  539. return false;
  540. };
  541. CalculationAction.prototype.updateMenu = function(toolbarItem,updateMenucallback)
  542. {
  543. toolbarItem.visible = this.ifContainsInteractiveDataContainer();
  544. if (! toolbarItem.visible)
  545. {
  546. return toolbarItem;
  547. }
  548. if (! this.areCalculationsPossible())
  549. {
  550. return this.toggleMenu(toolbarItem, false);
  551. }
  552. this.toggleMenu(toolbarItem, true);
  553. if(this.m_oCV.aQoSFunctions) {
  554. toolbarItem = this.buildCalculationMenuItemsAgainstSelection(toolbarItem);
  555. } else {
  556. toolbarItem = this.buildDynamicMenuItem(toolbarItem, "Calculation");
  557. }
  558. return toolbarItem;
  559. };
  560. CalculationAction.prototype.toggleMenu = function(toolbarItem, enabled)
  561. {
  562. if (enabled)
  563. {
  564. toolbarItem.iconClass = "calculate";
  565. toolbarItem.disabled = false;
  566. }
  567. else
  568. {
  569. toolbarItem.iconClass = "calculateDisabled";
  570. toolbarItem.disabled = true;
  571. }
  572. return toolbarItem;
  573. };
  574. CalculationAction.prototype.buildMenu = function(toolbarItem, buildMenuCallback)
  575. {
  576. toolbarItem.visible = this.ifContainsInteractiveDataContainer();
  577. if (! toolbarItem.visible)
  578. {
  579. return toolbarItem;
  580. }
  581. if (! this.areCalculationsPossible())
  582. {
  583. return this.toggleMenu(toolbarItem, false);
  584. }
  585. this.toggleMenu(toolbarItem, true);
  586. // check to see if we have the QoS properies, if not, go fetch them
  587. var viewerObject = this.getCognosViewer();
  588. if(typeof viewerObject.aQoSFunctions == "undefined")
  589. {
  590. // bux context menu's don't support asynch callback yet, once the fix is in to support it, we have to do this request synchrounously.
  591. this.fetchQoS(toolbarItem, buildMenuCallback, (typeof buildMenuCallback == "undefined") ? false : true);
  592. }
  593. if (typeof viewerObject.aQoSFunctions != "undefined")
  594. {
  595. return this.buildCalculationMenuItemsAgainstSelection(toolbarItem);
  596. }
  597. };
  598. CalculationAction.prototype.fetchQoS = function(toolbarItem, buildMenuCallback, asynch) {
  599. var callbacks = {
  600. customArguments: [toolbarItem, buildMenuCallback],
  601. "complete": {"object": this, "method": this.handleQoSResponse}
  602. };
  603. var asynchRequest = new AsynchJSONDispatcherEntry(this.m_oCV);
  604. asynchRequest.setCallbacks(callbacks);
  605. asynchRequest.addFormField("ui.action", "getQualityOfService");
  606. asynchRequest.addFormField("parameterValues", this.m_oCV.getExecutionParameters());
  607. asynchRequest.addFormField("bux", "true");
  608. asynchRequest.addNonEmptyStringFormField("modelPath", this.m_oCV.getModelPath());
  609. asynchRequest.addDefinedFormField("metaDataModelModificationTime", this.m_oCV.envParams["metaDataModelModificationTime"]);
  610. if (!asynch) {
  611. asynchRequest.forceSynchronous();
  612. }
  613. this.m_oCV.dispatchRequest(asynchRequest);
  614. };
  615. CalculationAction.prototype.handleQoSResponse = function(asynchJSONResponse, toolbarItem, buildMenuCallback)
  616. {
  617. this.m_oCV.aQoSFunctions = asynchJSONResponse.getResult();
  618. this.buildCalculationMenuItemsAgainstSelection(toolbarItem, buildMenuCallback);
  619. if (typeof buildMenuCallback == "function") {
  620. buildMenuCallback();
  621. }
  622. };
  623. CalculationAction.prototype.buildCalculationMenuItemsAgainstSelection = function(toolbarItem, buildMenuCallback)
  624. {
  625. var aCalculations = this.m_oCV.aBuxCalculations;
  626. var calcItems = [];
  627. for (var calcIndex=0; calcIndex < aCalculations.length; calcIndex++)
  628. {
  629. var calc = this.m_oCV.getCalculation(aCalculations[calcIndex]);
  630. // There might be some cases (GetQualityOfServer request is generated and async is forced) where this.m_oCV.aQoSFunctions is null because asynchJSONResponse.getResult() returns null (see COGCQ00261753).
  631. // This is a highly unlikly situation and the below condition is a safty net, just in case something goes really bad.
  632. // So, if this is the case we do not alow any calculations.
  633. if (this.m_oCV.aQoSFunctions == null || typeof this.m_oCV.aQoSFunctions == "undefined")
  634. {
  635. toolbarItem.disabled = true;
  636. toolbarItem.iconClass = "calculate";
  637. toolbarItem.items = null;
  638. return toolbarItem;
  639. }
  640. if (calc && calc.validSelectionLength(this.getCognosViewer().getSelectionController()) && this.m_oCV.aQoSFunctions.toString().indexOf(aCalculations[calcIndex]) != -1)
  641. {
  642. var newCalcItem = {};
  643. newCalcItem.name = aCalculations[calcIndex];
  644. newCalcItem.label = calc.getMenuItemString(true);
  645. newCalcItem.action = {};
  646. var sIconClass = "";
  647. if (aCalculations[calcIndex].indexOf("SwapOrder") != -1)
  648. {
  649. sIconClass = aCalculations[calcIndex].substring(0, aCalculations[calcIndex].indexOf("SwapOrder"));
  650. }
  651. else
  652. {
  653. sIconClass = aCalculations[calcIndex];
  654. }
  655. newCalcItem.iconClass = sIconClass;
  656. if(this.getNumberOfSelections() == 1)
  657. {
  658. newCalcItem.action.name = "ConstantOperandCalculation";
  659. newCalcItem.action.payload = aCalculations[calcIndex];
  660. }
  661. else
  662. {
  663. newCalcItem.action.name = aCalculations[calcIndex];
  664. newCalcItem.action.payload = "";
  665. }
  666. if(newCalcItem.action.name == "PercentDifferenceCalculation")
  667. {
  668. calcItems.push({separator: true});
  669. }
  670. newCalcItem.items = null;
  671. calcItems.push(newCalcItem);
  672. }
  673. }
  674. if(calcItems.length == 0)
  675. {
  676. this.toggleMenu(toolbarItem, false);
  677. calcItems.push({name: "None", label: RV_RES.IDS_JS_CALCULATION_SELECT_DATA, iconClass: "", action: null, items: null });
  678. } else {
  679. this.toggleMenu(toolbarItem, true);
  680. }
  681. toolbarItem.items = calcItems;
  682. return toolbarItem;
  683. };
  684. /**
  685. * Percent Difference calculation
  686. */
  687. function PercentDifferenceCalculationAction(){
  688. this.m_sAction = "PercentDifference";
  689. this.m_menuBuilderClass = "PercentDifferenceCalculation";
  690. }
  691. PercentDifferenceCalculationAction.prototype = new CalculationAction();
  692. /**
  693. * Percent Different with reversed order of selection
  694. */
  695. function PercentDifferenceCalculationSwapOrderAction() {
  696. this.m_sAction = "PercentDifference";
  697. this.m_menuBuilderClass = "PercentDifferenceCalculationSwapOrder";
  698. this.m_swapSelectionOrder = true;
  699. }
  700. PercentDifferenceCalculationSwapOrderAction.prototype = new CalculationAction();
  701. /**
  702. * Addition calculation
  703. */
  704. function AdditionCalculationAction(){
  705. this.m_sAction = "Addition";
  706. this.m_menuBuilderClass = "AdditionCalculation";
  707. }
  708. AdditionCalculationAction.prototype = new CalculationAction();
  709. /**
  710. * Subtraction calculation
  711. */
  712. function SubtractionCalculationAction(){
  713. this.m_sAction = "Subtraction";
  714. this.m_menuBuilderClass = "SubtractionCalculation";
  715. }
  716. SubtractionCalculationAction.prototype = new CalculationAction();
  717. /**
  718. * Subtraction calculation with reversed selection (i.e. A-B vs B-A)
  719. */
  720. function SubtractionCalculationSwapOrderAction() {
  721. this.m_sAction = "Subtraction";
  722. this.m_menuBuilderClass = "SubtractionCalculationSwapOrder";
  723. this.m_swapSelectionOrder = true;
  724. }
  725. SubtractionCalculationSwapOrderAction.prototype = new CalculationAction();
  726. /**
  727. * Multiplication calculation
  728. */
  729. function MultiplicationCalculationAction(){
  730. this.m_sAction = "Multiplication";
  731. this.m_menuBuilderClass = "MultiplicationCalculation";
  732. }
  733. MultiplicationCalculationAction.prototype = new CalculationAction();
  734. /**
  735. * Division calculation
  736. */
  737. function DivisionCalculationAction(){
  738. this.m_sAction = "Division";
  739. this.m_menuBuilderClass = "DivisionCalculation";
  740. }
  741. DivisionCalculationAction.prototype = new CalculationAction();
  742. /**
  743. * Division calculation with reversed selection (i.e. A / B vs. B / A)
  744. * @return
  745. */
  746. function DivisionCalculationSwapOrderAction() {
  747. this.m_sAction = "Division";
  748. this.m_menuBuilderClass = "DivisionCalculationSwapOrder";
  749. this.m_swapSelectionOrder = true;
  750. }
  751. DivisionCalculationSwapOrderAction.prototype = new CalculationAction();
  752. function ConstantOperandCalculationAction()
  753. {
  754. this.m_action = null;
  755. }
  756. ConstantOperandCalculationAction.prototype = new CognosViewerAction();
  757. ConstantOperandCalculationAction.prototype.setRequestParms = function(payload)
  758. {
  759. this.m_action = payload;
  760. };
  761. ConstantOperandCalculationAction.prototype.execute = function()
  762. {
  763. var cognosViewerObjectString = getCognosViewerObjectString(this.m_oCV.getId());
  764. var action = this.m_action;
  765. var calculation = this.m_oCV.getCalculation(action);
  766. var menuItemString = calculation.getMenuItemString(true);
  767. var dialogTitle = RV_RES.IDS_JS_CALCULATE_ENTER_NUMBER_TITLE;
  768. var dialogDescription = RV_RES.IDS_JS_CALCULATE_ENTER_NUMBER_DESCRIPTION;
  769. dialogDescription = dialogDescription.substring(0, dialogDescription.indexOf("{0}")) + menuItemString + dialogDescription.substring(dialogDescription.indexOf("{0}") + 3);
  770. var enterNumberLabel = RV_RES.IDS_JS_CALCULATE_ENTER_NUMBER;
  771. var contentLocale = this.m_oCV.envParams["contentLocale"];
  772. var calculationDialog = new viewer.dialogs.CalculationDialog({
  773. sTitle:dialogTitle,
  774. sLabel:enterNumberLabel,
  775. sDescription:dialogDescription,
  776. sContentLocale : contentLocale,
  777. okHandler: function(value)
  778. {
  779. window[cognosViewerObjectString].executeAction(action, {constant:value});
  780. },
  781. cancelHandler: function() {}
  782. });
  783. calculationDialog.startup();
  784. window.setTimeout(function () { calculationDialog.show(); },0);
  785. };