VisSelected.js 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. 'use strict';
  2. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  3. /**
  4. * Licensed Materials - Property of IBM
  5. * IBM Cognos Products: BI Cloud (C) Copyright IBM Corp. 2020
  6. * US Government Users Restricted Rights - Use, duplication or disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
  7. */
  8. define(['../../../../lib/@waca/dashboard-common/dist/core/APIFactory', './api/SelectedAPI', '../../../../util/EventUtils', 'underscore'], function (APIFactory, SelectedAPI, EventUtils, _) {
  9. /**
  10. * VisSelected provides a fast lookup on the selected values for a particular item or tuple.
  11. */
  12. var VisSelected = function () {
  13. /**
  14. * constructor attributes:
  15. * pageContextAPI - the pageContextAPI
  16. * itemIds - an array of itemIds
  17. */
  18. function VisSelected(attributes) {
  19. var _this = this;
  20. _classCallCheck(this, VisSelected);
  21. this._includeParents = attributes.includeParents;
  22. this._ignoreEdgeSelections = attributes.ignoreEdgeSelections;
  23. this._edgeSelections = [];
  24. this._pointSelections = {};
  25. this._selectedParents = {};
  26. this._pageContextAPI = attributes.pageContextAPI;
  27. this._itemIds = attributes.itemIds;
  28. this._sourceId = attributes.sourceId;
  29. this.synchronizeData = attributes.synchronizeData;
  30. var pageContextMatchParams = {
  31. origin: 'visualization',
  32. scope: attributes.scope,
  33. eventGroupId: attributes.eventGroupId
  34. };
  35. if (!this._ignoreEdgeSelections) {
  36. _.each(this._itemIds, function (itemId) {
  37. var pci = _this.synchronizeData.getPageContextItem(_this._sourceId, _this._pageContextAPI, itemId, pageContextMatchParams);
  38. if (pci && pci.getValueCount()) {
  39. var selectedValueMap = {};
  40. var aTupleValues = [];
  41. _.each(pci.getValueIds(), function (valueId) {
  42. selectedValueMap[valueId] = 1;
  43. aTupleValues.push(valueId);
  44. });
  45. _this._edgeSelections.push(selectedValueMap);
  46. } else {
  47. _this._edgeSelections.push({});
  48. }
  49. });
  50. }
  51. //Lookup pageContext entries for the items of interest and place the selected datapoints (if any) in a map.
  52. var hierarchies = _.map(this._itemIds, function (itemId) {
  53. return {
  54. hierarchyUniqueName: itemId
  55. };
  56. });
  57. for (var i = this._itemIds.length; i > 1; --i) {
  58. this._addDataPointSelections(_.head(hierarchies, i), pageContextMatchParams, attributes.includeParents);
  59. }
  60. //Cache 'parent selected points' to detect is something is a 'selectedChild point' (selectedChild points of edges are handled above)
  61. //A selected child point/cell is not really selected itself but are highlighted if there are selections of 'parent points'
  62. //When asking if point A.B.C is selected, we want to know if A.B is selected so that we can return it as a 'selectedChild'.
  63. //When asking if A.B.C.D is selected we want to know if A.B, A.B.C or B.C are selected so that we can return it as a 'selectedChild'
  64. for (var start = 0; start < this._itemIds.length - 1; ++start) {
  65. for (var end = this._itemIds.length; end > start + 1; --end) {
  66. //Set includeParents to false for selected children...we don't want to process parents of selected children again.
  67. this._addDataPointSelections(hierarchies.slice(start, end), pageContextMatchParams, /*includeParents*/false);
  68. }
  69. }
  70. }
  71. VisSelected.prototype.getAPI = function getAPI() {
  72. if (!this._api) {
  73. this._api = APIFactory.createAPI(this, [SelectedAPI]);
  74. }
  75. return this._api;
  76. };
  77. VisSelected.prototype._addDataPointSelections = function _addDataPointSelections(hierarchies, pageContextMatchParams, includeParents) {
  78. var pcpoint = this._pageContextAPI.getPageContextItem(_.extend({
  79. hierarchies: hierarchies
  80. }, pageContextMatchParams));
  81. if (pcpoint && pcpoint.getValueCount()) {
  82. _.each(pcpoint.getDataPoints(), function (dataPoint) {
  83. this._pointSelections[this._getDataPointKey(dataPoint)] = 1;
  84. if (includeParents) {
  85. this._addSelectedParents(this._itemIds, dataPoint);
  86. }
  87. }.bind(this));
  88. }
  89. };
  90. /**
  91. * Given Year, Product, OrderMethod, gender
  92. * 2007, cars, fax, male
  93. * Year=2007
  94. * Year=2007__Product=Cars
  95. * Year=2007__Product=Cars__OrderMethod=Fax
  96. * Year=2007__Product=Cars__OrderMethod=Fax__Gender=male
  97. * Product=cars
  98. * Product=cars__OrderMethod=fax
  99. * Product=cars__OrderMethod=fax__gender=male
  100. * OrderMethod=fax__gender=male
  101. * gender=male
  102. *
  103. * ASSUMPTION - all items from the beginning of an edge are provided
  104. * @return true for any in-order permutation
  105. */
  106. VisSelected.prototype._addSelectedParents = function _addSelectedParents(itemIds, dataPoint) {
  107. //Generate a tuple for each of length 1 to length n-1 where n-1 is the length of the array.
  108. var itemList = itemIds;
  109. var tuple = dataPoint;
  110. while (itemList.length > 0) {
  111. for (var tupleLength = 1; tupleLength < itemList.length; ++tupleLength) {
  112. this._selectedParents[this._getParentKey(_.first(itemList, itemList.length), _.first(tuple, tupleLength))] = 1;
  113. }
  114. itemList = _.rest(itemList);
  115. tuple = _.rest(tuple);
  116. }
  117. };
  118. /**
  119. * length of the longest selected point
  120. * AxBxC returns 3
  121. * AxB returns 2
  122. */
  123. VisSelected.prototype._getMaxPointSelectionLength = function _getMaxPointSelectionLength() {
  124. var max = 0;
  125. var selections = Object.getOwnPropertyNames(this._pointSelections);
  126. for (var i = 0; i < selections.length; i++) {
  127. max = Math.max(selections[i].split(EventUtils.SEPARATOR).length, max);
  128. }
  129. return max;
  130. };
  131. /**
  132. * @param tuple - a tuple of form [ { u:'x'}, { u:'y'} ] where each entry in the array corresponds to the itemIds array.
  133. * (also supports form [ 'x', 'y'] ) where x and y are assumed to be use values.
  134. * example: isSelected [ {u:'2005'}, {u:'Fax'} ]
  135. */
  136. VisSelected.prototype.isSelected = function isSelected(tuple) {
  137. //First process the edges....For edges, if at least 1 is selected, the node is selected.
  138. for (var i = 0; i < tuple.length; ++i) {
  139. if (tuple[i] && _.isObject(this._edgeSelections[i]) && this._edgeSelections[i][tuple[i].u || tuple[i]]) {
  140. //Any match of an edge is a match.
  141. return true;
  142. }
  143. }
  144. //Process dataPoints....it has to be an exact match.
  145. if (this._pointSelections[this._getDataPointKey(tuple)]) {
  146. return true;
  147. }
  148. //if 'A' is a selected value, A.B is a selectedChild, A.B.C is a selectedChild etc.
  149. //if 'A.B' is a selected datapoint, A.B.C is a selectedChild (A is a parent)
  150. //if 'A.B.C' is a selected datapoint, A.B.C.D is a selectedChild but so is B.C.D (A.B, A are parents)
  151. var maxLength = this._getMaxPointSelectionLength();
  152. for (var start = 0; start < tuple.length; ++start) {
  153. for (var end = tuple.length; end >= start; --end) {
  154. var slice = tuple.slice(start, end);
  155. if (slice.length <= maxLength && this._pointSelections[this._getDataPointKey(slice)]) {
  156. return true;
  157. }
  158. }
  159. }
  160. return false;
  161. };
  162. VisSelected.prototype.isSelectedParent = function isSelectedParent(hierarchies, dataPoint) {
  163. return this._selectedParents[this._getParentKey(hierarchies, dataPoint)] ? true : false;
  164. };
  165. /**
  166. * Same as isSelected but for a simple value object.
  167. * @param value - a value of form { u: 'x' }
  168. */
  169. VisSelected.prototype.isValueSelected = function isValueSelected(value) {
  170. return this.isSelected([value]);
  171. };
  172. VisSelected.prototype.hasSelections = function hasSelections() {
  173. var hasEdgeSelections = _.find(this._edgeSelections, function (edge) {
  174. return _.keys(edge).length > 0;
  175. });
  176. return hasEdgeSelections || _.keys(this._pointSelections).length ? true : false;
  177. };
  178. VisSelected.prototype._getDataPointKey = function _getDataPointKey(dataPoint) {
  179. return EventUtils.getDataPointKey(dataPoint);
  180. };
  181. VisSelected.prototype._getParentKey = function _getParentKey(hierarchies, dataPoint) {
  182. var key = '';
  183. var tempDataPoint = _.clone(dataPoint); //Make a copy to sort and keep dataPoint unchanged.
  184. var sortedDataPoint = tempDataPoint.sort(EventUtils.compareDataPointKey);
  185. _.each(sortedDataPoint, function (tuplePart, partIdx) {
  186. key += hierarchies[partIdx] + '=' + tuplePart.u + EventUtils.SEPARATOR;
  187. });
  188. return key.slice(0, -1);
  189. };
  190. VisSelected.prototype.getSelectedKeys = function getSelectedKeys() {
  191. var selectedKeys = [];
  192. //Get edge selection keys
  193. _.each(this._edgeSelections, function (edgeSelection) {
  194. selectedKeys = selectedKeys.concat(_.keys(edgeSelection));
  195. });
  196. //Get datapoint keys
  197. selectedKeys = selectedKeys.concat(_.keys(this._pointSelections));
  198. return selectedKeys;
  199. };
  200. return VisSelected;
  201. }();
  202. return VisSelected;
  203. });
  204. //# sourceMappingURL=VisSelected.js.map