cvsort.js 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530
  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. function CognosViewerSort( event, oCV ) {
  13. this.m_oCV = oCV;
  14. if( event )
  15. {
  16. this.m_oEvent = event;
  17. this.m_oNode = getCrossBrowserNode(event, true);
  18. }
  19. }
  20. CognosViewerSort.prototype.setNode = function( node )
  21. {
  22. this.m_oNode = node;
  23. };
  24. CognosViewerSort.prototype.getNode = function()
  25. {
  26. return this.m_oNode;
  27. };
  28. /*
  29. * Checks to see if this is a sort action
  30. */
  31. CognosViewerSort.prototype.isSort = function() {
  32. if(this.m_oNode && this.m_oNode.nodeName == 'IMG' && (this.m_oNode.id).indexOf('sortimg') >= 0 )
  33. {
  34. return true;
  35. }
  36. else
  37. {
  38. return false;
  39. }
  40. };
  41. CognosViewerSort.prototype.execute = function() {
  42. var selectionController = getCognosViewerSCObjectRef(this.m_oCV.getId());
  43. selectionController.selectSingleDomNode(this.m_oNode.parentNode);
  44. var sortAction = this.getSortAction();
  45. sortAction.setCognosViewer(this.m_oCV);
  46. sortAction.execute();
  47. if (window.gViewerLogger) {
  48. window.gViewerLogger.addContextInfo(selectionController);
  49. }
  50. };
  51. /*
  52. * The order of sort is ascending, descending and none.
  53. * Figure out what the current sort should be based on previous sort order.
  54. * Eg. if previous sort order is ascending, then next sort order should be descending.
  55. */
  56. CognosViewerSort.prototype.getSortAction = function() {
  57. var sortAction = this.m_oCV.getAction("Sort");
  58. var sortOrder = this.m_oNode.getAttribute( 'sortOrder' );
  59. if( sortOrder.indexOf('nosort') != -1 )
  60. {
  61. sortAction.setRequestParms({order:"ascending", type:"value"});
  62. }
  63. else if ( sortOrder.indexOf('ascending') != -1 )
  64. {
  65. sortAction.setRequestParms({order:"descending", type:"value"});
  66. }
  67. else if( sortOrder.indexOf('descending') != -1)
  68. {
  69. sortAction.setRequestParms({order:"none", type:"value"});
  70. }
  71. return sortAction;
  72. };
  73. function SortAction()
  74. {
  75. this.m_sAction = "Sort";
  76. this.m_sortOrder = "none";
  77. this.m_sortType = "";
  78. this.m_sItem = "";
  79. this.m_sId="";
  80. }
  81. SortAction.prototype = new ModifyReportAction();
  82. SortAction.prototype.doExecute = function() {
  83. //Abort execute iff existing sort is none and new sort is none
  84. if (this.m_sortOrder === "none") {
  85. //Allow the execute if there is no container - i.e. no field is selected.
  86. //This occurs when the user cancels a sort from the infobar.
  87. if (this.getContainerId(this.m_oCV.getSelectionController())) {
  88. var currentSort = this.getCurrentSortFromSelection();
  89. if (this.m_sortType === "value" && currentSort.indexOf("sortByValue") === -1) {
  90. return false;
  91. } else if (this.m_sortType === "label" && currentSort.indexOf("sortByLabel") === -1) {
  92. return false;
  93. }
  94. }
  95. }
  96. return true;
  97. };
  98. SortAction.prototype.execute = function() {
  99. if(this.doExecute()) {
  100. ModifyReportAction.prototype.execute.call(this);
  101. }
  102. };
  103. SortAction.prototype.getUndoHint = function()
  104. {
  105. if (this.m_sortOrder == "none") {
  106. return RV_RES.IDS_JS_DONT_SORT;
  107. }
  108. else {
  109. return RV_RES.IDS_JS_SORT;
  110. }
  111. };
  112. SortAction.prototype.setRequestParms = function(payload)
  113. {
  114. this.m_sortOrder = payload.order;
  115. this.m_sortType = payload.type;
  116. if (payload.id!=null && typeof payload.id != "undefined") {
  117. this.m_sId = payload.id;
  118. }
  119. if (payload.item!=null && typeof payload.item != "undefined") {
  120. this.m_sItem = payload.item;
  121. }
  122. };
  123. SortAction.prototype.addActionContextAdditionalParms = function()
  124. {
  125. var selectionController = this.m_oCV.getSelectionController();
  126. var parms = "<order>" + this.m_sortOrder + "</order>";
  127. if(this.m_sortType == "label")
  128. {
  129. parms += "<byLabel/>";
  130. }
  131. if (this.getContainerId(selectionController)=="" && this.m_sId != null && typeof this.m_sId != "undefined" && this.m_sId != "") {
  132. parms+= ("<id>" + xml_encode(this.m_sId) + "</id>");
  133. }
  134. if (this.m_sItem != null && typeof this.m_sItem != "undefined" && this.m_sItem!="") {
  135. parms+= ("<item>" + xml_encode(this.m_sItem) + "</item>");
  136. }
  137. parms += this.addClientContextData(/*maxValuesPerRDI*/3);
  138. parms += this.getSelectedCellTags();
  139. return parms;
  140. };
  141. SortAction.prototype.toggleMenu = function(jsonSpec, enabled)
  142. {
  143. if (enabled)
  144. {
  145. jsonSpec.iconClass = "sort";
  146. jsonSpec.disabled = false;
  147. }
  148. else
  149. {
  150. jsonSpec.iconClass = "sortDisabled";
  151. jsonSpec.disabled = true;
  152. }
  153. return jsonSpec;
  154. };
  155. SortAction.prototype.updateMenu = function(jsonSpec)
  156. {
  157. jsonSpec.visible = this.ifContainsInteractiveDataContainer();
  158. if (! jsonSpec.visible)
  159. {
  160. return jsonSpec;
  161. }
  162. this.buildMenu(jsonSpec);
  163. if (jsonSpec.disabled == true) {
  164. return this.toggleMenu(jsonSpec, false);
  165. }
  166. return this.buildDynamicMenuItem(this.toggleMenu(jsonSpec, true), "Sort");
  167. };
  168. SortAction.prototype.buildSelectedItemsString = function(selectedObjects, isSortByValue/*isSortByValue=false means sortByLabel*/, containerReportInfo)
  169. {
  170. try {
  171. var selObj = selectedObjects[selectedObjects.length -1];
  172. if (isSortByValue) {
  173. var itemsLabel = selObj.getDisplayValues()[0];
  174. if (typeof itemsLabel == "undefined") {
  175. itemsLabel = selObj.getUseValues()[0][0];
  176. }
  177. return itemsLabel;
  178. } else {
  179. return selObj.getDataItemDisplayValue(containerReportInfo);
  180. }
  181. }
  182. catch (e) {
  183. if (console && console.log) {
  184. console.log(e);
  185. }
  186. }
  187. };
  188. SortAction.prototype.buildMenu = function(jsonSpec)
  189. {
  190. jsonSpec.visible = this.ifContainsInteractiveDataContainer();
  191. if (! jsonSpec.visible)
  192. {
  193. return jsonSpec;
  194. }
  195. if(!this.isSelectionSortable())
  196. {
  197. return this.toggleMenu(jsonSpec, false);
  198. }
  199. jsonSpec = this.toggleMenu(jsonSpec, true);
  200. var sortItems = [];
  201. var selectionController = this.m_oCV.getSelectionController();
  202. var selectedObjects = selectionController.getAllSelectedObjects();
  203. if(selectedObjects.length == 1 && selectedObjects[0].isHomeCell() == false)
  204. {
  205. var containerType = selectionController.getDataContainerType();
  206. var containerId = this.getContainerId( selectionController );
  207. var selectedReportInfo = this.getReportInfo(containerId);
  208. //if the selection is on the section of the sectioned list, the containerType is "".
  209. if (containerType == "" && !this.isSelectionOnChart() && selectedObjects[0].getLayoutType() == "section") {
  210. if (selectedReportInfo != null) {
  211. containerType = selectedReportInfo.displayTypeId;
  212. }
  213. }
  214. var reportInfo, sItemLabel, sSelectionInfo;
  215. var currentSortFromSelection = this.getCurrentSortFromSelection();
  216. var bSelectionOnChart = this.isSelectionOnChart();
  217. var bSortByValue = currentSortFromSelection.indexOf("sortByValue") != -1;
  218. var bSortByValueAscending = currentSortFromSelection.indexOf("sortByValueAscending") != -1;
  219. var bSortByValueDescending = currentSortFromSelection.indexOf("sortByValueDescending") != -1;
  220. var bIsIWidgetMobile = this.m_oCV.isIWidgetMobile();
  221. if(containerType == "list" )
  222. {
  223. var oSortByValueAscendingMenuItem = { name: "SortAscending", label: RV_RES.IDS_JS_SORT_ASCENDING, action: { name: "Sort", payload: {order:"ascending", type:"value"} }, items: null };
  224. this.addMenuItemChecked(bSortByValueAscending, oSortByValueAscendingMenuItem, "sortAscending");
  225. sortItems.push(oSortByValueAscendingMenuItem);
  226. var oSortByValueDescendingMenuItem = { name: "SortDescending", label: RV_RES.IDS_JS_SORT_DESCENDING, action: { name: "Sort", payload: { order:"descending", type:"value"} }, items: null };
  227. this.addMenuItemChecked(bSortByValueDescending, oSortByValueDescendingMenuItem, "sortDescending");
  228. sortItems.push(oSortByValueDescendingMenuItem);
  229. var oSortMenuItem = { name: "DontSort", label: RV_RES.IDS_JS_DONT_SORT, action: { name: "Sort", payload: {order:"none",type:"value"} }, items: null };
  230. this.addMenuItemChecked(!bSortByValue, oSortMenuItem, "sortNone");
  231. sortItems.push(oSortMenuItem);
  232. }
  233. else if (containerType == "crosstab" || bSelectionOnChart)
  234. {
  235. if (selectedObjects[0].getLayoutType() == 'columnTitle' || bSelectionOnChart)
  236. {
  237. reportInfo = this.m_oCV.getRAPReportInfo();
  238. if(this.canSortByValueOnCrosstab(selectedObjects[0], reportInfo))
  239. {
  240. sItemLabel = RV_RES.IDS_JS_SORT_BY_VALUE;
  241. // need to show what item will get sorted if we're dealing with charts since
  242. // charts don't show selection
  243. if (bSelectionOnChart) {
  244. sSelectionInfo = this.buildSelectedItemsString(selectedObjects, true /*sortByValue*/, selectedReportInfo);
  245. if (typeof sSelectionInfo !== "undefined") {
  246. sItemLabel += ":" + sSelectionInfo;
  247. }
  248. }
  249. var oSortByValueMenuItem = { name: "SortByValue", label: sItemLabel, action: null, items: [{ name: "Ascending", label: RV_RES.IDS_JS_SORT_BY_ASCENDING, action: { name: "Sort", payload: {order:"ascending",type:"value"} }, items: null }, { name: "Descending", label: RV_RES.IDS_JS_SORT_BY_DESCENDING, action: { name: "Sort", payload: {order:"descending",type:"value"} }, items: null }, { name: "SortNone", label: RV_RES.IDS_JS_DONT_SORT, action: { name: "Sort", payload: {order:"none",type:"value"} }, items: null } ] };
  250. this.addMenuItemChecked(bSortByValue, oSortByValueMenuItem);
  251. this.addMenuItemChecked(bSortByValueAscending, oSortByValueMenuItem.items[0], "sortAscending");
  252. this.addMenuItemChecked(bSortByValueDescending, oSortByValueMenuItem.items[1], "sortDescending");
  253. this.addMenuItemChecked(!bSortByValue, oSortByValueMenuItem.items[2], "sortNone");
  254. if (bIsIWidgetMobile) {
  255. oSortByValueMenuItem.flatten = true;
  256. }
  257. sortItems.push(oSortByValueMenuItem);
  258. }
  259. if(this.canSortByLabelOnCrosstab(selectedObjects[0]))
  260. {
  261. sItemLabel = RV_RES.IDS_JS_SORT_BY_LABEL;
  262. // need to show what item will get sorted if we're dealing with charts since
  263. // charts don't show selection
  264. if (bSelectionOnChart) {
  265. sSelectionInfo = this.buildSelectedItemsString(selectedObjects, false /*sortByLabel*/, selectedReportInfo);
  266. if (typeof sSelectionInfo !== "undefined") {
  267. sItemLabel += ":" + sSelectionInfo;
  268. }
  269. }
  270. var oSortByLabelMenuItem = { name: "SortByLabel", label: sItemLabel, action: null, items: [{ name: "Ascending", label: RV_RES.IDS_JS_SORT_BY_ASCENDING, action: { name: "Sort", payload: {order:"ascending",type:"label"} }, items: null }, { name: "Descending", label: RV_RES.IDS_JS_SORT_BY_DESCENDING, action: { name: "Sort", payload: {order:"descending",type:"label"} }, items: null }, { name: "SortNone", label: RV_RES.IDS_JS_DONT_SORT, action: { name: "Sort", payload: {order:"none",type:"label"} }, items: null } ] };
  271. var bSortByLabel = currentSortFromSelection.indexOf("sortByLabel") != -1;
  272. this.addMenuItemChecked(bSortByLabel, oSortByLabelMenuItem);
  273. this.addMenuItemChecked(currentSortFromSelection.indexOf("sortByLabelAscending") != -1, oSortByLabelMenuItem.items[0], "sortAscending");
  274. this.addMenuItemChecked(currentSortFromSelection.indexOf("sortByLabelDescending") != -1, oSortByLabelMenuItem.items[1], "sortDescending");
  275. this.addMenuItemChecked(!bSortByLabel, oSortByLabelMenuItem.items[2], "sortNone");
  276. if (bIsIWidgetMobile) {
  277. oSortByLabelMenuItem.flatten = true;
  278. }
  279. sortItems.push(oSortByLabelMenuItem);
  280. }
  281. }
  282. }
  283. }
  284. if(sortItems.length == 0)
  285. {
  286. this.toggleMenu(jsonSpec, false);
  287. }
  288. else
  289. {
  290. if (bIsIWidgetMobile) {
  291. if (containerType == "crosstab" || bSelectionOnChart) {
  292. jsonSpec.useChildrenItems = true;
  293. }
  294. else {
  295. jsonSpec.flatten = true;
  296. }
  297. }
  298. jsonSpec.items = sortItems;
  299. this.toggleMenu(jsonSpec, true);
  300. }
  301. return jsonSpec;
  302. };
  303. SortAction.prototype.isSelectionSortable = function()
  304. {
  305. var selectionController = this.m_oCV.getSelectionController();
  306. var selectedObjects = selectionController.getAllSelectedObjects();
  307. if (selectedObjects.length == 1) {
  308. var selectedObject = selectedObjects[0];
  309. //If the select object should be disabled when the user selects a measured cell(s).
  310. if (selectionController.getDataContainerType() == "crosstab" && selectedObject.getLayoutType() == 'datavalue')
  311. {
  312. return false;
  313. }
  314. if (selectionController.hasSelectedChartNodes())
  315. {
  316. var node = selectedObject.getArea();
  317. if (node.nodeName == 'AREA' || node.nodeName == 'IMG')
  318. {
  319. return selectedObjects[0].getLayoutType() == 'ordinalAxisLabel' || selectedObjects[0].getLayoutType() == 'legendLabel';
  320. }
  321. }
  322. else
  323. {
  324. var data = selectedObject.getDataItems();
  325. if(selectedObject.getCellRef().getAttribute("type") == "datavalue" && !(data && data.length)) {
  326. //Not sortable if there is no logical data in the selection
  327. return false;
  328. }
  329. var oCell = selectedObject.getCellRef();
  330. if (oCell.getAttribute("no_data_item_column") === "true") {
  331. return false;
  332. }
  333. if (oCell.getAttribute("canSort") != "false") {
  334. return true;
  335. }
  336. }
  337. }
  338. return false;
  339. };
  340. SortAction.prototype.getCurrentSortFromSelection = function()
  341. {
  342. var containerId = this.getContainerId(this.m_oCV.getSelectionController());
  343. var oRAPReportInfo = this.m_oCV.getRAPReportInfo();
  344. var currentSortFromSelection = "";
  345. if(containerId != "" && oRAPReportInfo) {
  346. var container = oRAPReportInfo.getContainer(containerId);
  347. if(typeof container.sort != "undefined") {
  348. var selectionController = this.m_oCV.getSelectionController();
  349. var selectedObjects = selectionController.getAllSelectedObjects();
  350. if(selectedObjects.length == 1) {
  351. var dataItems = selectedObjects[0].getDataItems();
  352. if(dataItems.length < 1) {
  353. return currentSortFromSelection;
  354. }
  355. var dataItem = dataItems[0][0];
  356. for(var index = 0; index < container.sort.length; ++index) {
  357. var sortInfo = container.sort[index];
  358. if(typeof sortInfo.labels == "string" && sortInfo.labels == dataItem) {
  359. currentSortFromSelection += sortInfo.order == "descending" ? "sortByLabelDescending" : "sortByLabelAscending";
  360. }
  361. if(typeof sortInfo.valuesOf == "string" && (sortInfo.valuesOf == dataItem || this.isSortedValueOnRenamedColumn(selectedObjects[0], sortInfo))) {
  362. currentSortFromSelection += sortInfo.order == "descending" ? "sortByValueDescending" : "sortByValueAscending";
  363. }
  364. else if(sortInfo.valuesOf instanceof Array) {
  365. var match = true;
  366. for(var valueSortIdx = 0; valueSortIdx < sortInfo.valuesOf.length; ++valueSortIdx) {
  367. if(valueSortIdx < selectedObjects[0].m_contextIds[0].length) {
  368. var ctx = selectedObjects[0].m_contextIds[0][valueSortIdx];
  369. var selectionDisplayValue = selectionController.getDisplayValue(ctx);
  370. var sortDisplayValue = this.findItemLabel(container, sortInfo.valuesOf[valueSortIdx].item);
  371. if(sortDisplayValue != selectionDisplayValue) {
  372. match = false;
  373. break;
  374. }
  375. }
  376. }
  377. if(match) {
  378. currentSortFromSelection += sortInfo.valuesOf[0].order == "descending" ? "sortByValueDescending" : "sortByValueAscending";
  379. }
  380. }
  381. }
  382. }
  383. }
  384. }
  385. return currentSortFromSelection;
  386. };
  387. SortAction.prototype.isSortedValueOnRenamedColumn =function(selectedObject, sortInfo){
  388. if(sortInfo && selectedObject){
  389. return (sortInfo.valuesOf === selectedObject.getColumnRP_Name() && selectedObject.getLayoutType() === "columnTitle");
  390. }
  391. };
  392. SortAction.prototype.findItemLabel = function(container, item) {
  393. var itemInfo = container.itemInfo;
  394. if (itemInfo) {
  395. for (var i = 0; i < itemInfo.length; i++) {
  396. if (itemInfo[i].item === item) {
  397. if (itemInfo[i].itemLabel) {
  398. return itemInfo[i].itemLabel;
  399. }
  400. break;
  401. }
  402. }
  403. }
  404. return item;
  405. };
  406. SortAction.prototype.canSortByValueOnCrosstab = function(selectedObject, reportInfo)
  407. {
  408. var selectionController = this.m_oCV.getSelectionController();
  409. var containerId = this.getContainerId(this.m_oCV.getSelectionController());
  410. if (selectionController.isRelational() == true) {
  411. return false;
  412. }
  413. if (selectionController.selectionsHaveCalculationMetadata() && this.selectedObjectIsLeaf(containerId, selectedObject, reportInfo)) {
  414. //The DAM layer allows "tagging" of calculation values which are part of sets with uuid designators.
  415. //These uuid's are simply passed through and returned as if they were mun's (but are not muns and can't be used in expressions)
  416. //We don't support these as discrete values.
  417. var aMuns = selectedObject.getMuns()[0];
  418. for (var index = 0; index < aMuns.length; ++index)
  419. {
  420. if (aMuns[index] != null && aMuns[index].indexOf("uuid:") >= 0)
  421. {
  422. return false;
  423. }
  424. }
  425. return true;
  426. }
  427. return false;
  428. };
  429. SortAction.prototype.selectedObjectIsLeaf = function (containerId, selectedObject, reportInfo)
  430. {
  431. if (reportInfo) {
  432. var dataItems = selectedObject.getDataItems();
  433. if (dataItems != null && typeof dataItems != "undefined" && dataItems.length > 0) {
  434. var oDrillability = reportInfo.getDrillability(containerId, dataItems[0][0]);
  435. if (oDrillability) {
  436. return oDrillability.leaf == true;
  437. }
  438. }
  439. }
  440. return false;
  441. };
  442. SortAction.prototype.canSortByLabelOnCrosstab = function(selectedObject)
  443. {
  444. var selectionController = this.m_oCV.getSelectionController();
  445. var selectedObjects = selectionController.getAllSelectedObjects();
  446. if(selectedObjects.length == 1) {
  447. // FIXME: This variable (selectedObject) is masking the first parameter. Remove variable or the parameter.
  448. var selectedObject = selectedObjects[0];
  449. if (this.isSelectSingleMember(selectedObject)==false)
  450. {
  451. if (selectionController.selectionsNonMeasureWithMUN() || !selectionController.selectionsHaveCalculationMetadata()) {
  452. return true;
  453. }
  454. }
  455. }
  456. return false;
  457. };