CrosstabEventTarget.js 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490
  1. 'use strict';
  2. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  3. function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
  4. function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
  5. /**
  6. * Licensed Materials - Property of IBM
  7. * IBM Cognos Products: BI Cloud (C) Copyright IBM Corp. 2017, 2019
  8. * US Government Users Restricted Rights - Use, duplication or disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
  9. */
  10. define(['jquery', '../common/NonVIPREventTarget', 'underscore'], function ($, NonVIPREventTarget, _) {
  11. var EVENTTYPE = {
  12. CUSTOMDATA: 'customdata',
  13. DATAPOINT: 'datapoint',
  14. ITEMCLASS: 'itemclass',
  15. ITEM: 'item',
  16. SUMMARY: 'summary',
  17. EXPANDED: 'expanded'
  18. };
  19. var CELL_TYPE = {
  20. ROW: 'row',
  21. COLUMN: 'column'
  22. };
  23. var AREA_TYPE = {
  24. ROW: 'cell_edge_row',
  25. COLUMN: 'cell_edge_column',
  26. CELL: 'cell',
  27. MEASURE: 'values',
  28. SUMMARY: 'summary'
  29. };
  30. var SLOTID = {
  31. COLUMN: 'column_level1',
  32. ROW: 'row_level1',
  33. VALUES: 'values',
  34. HEAT: 'heat'
  35. };
  36. var CrosstabEventTarget = function (_NonVIPREventTarget) {
  37. _inherits(CrosstabEventTarget, _NonVIPREventTarget);
  38. function CrosstabEventTarget() {
  39. _classCallCheck(this, CrosstabEventTarget);
  40. for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
  41. args[_key] = arguments[_key];
  42. }
  43. var _this = _possibleConstructorReturn(this, _NonVIPREventTarget.call.apply(_NonVIPREventTarget, [this].concat(args)));
  44. var options = args[0] || {};
  45. _this.ownerWidget = options.ownerWidget;
  46. _this.view = options.view;
  47. return _this;
  48. }
  49. /**
  50. * Get the array of event targets based on the event.
  51. * Event target represents a data point object that corresponds to the event.
  52. *
  53. * @param event Event object
  54. */
  55. CrosstabEventTarget.prototype.getEventTargets = function getEventTargets(event) {
  56. var _this2 = this;
  57. if (!this._isValidEvent(event)) {
  58. return [];
  59. }
  60. var targets = [];
  61. var items = this._getEventTargetItem(event);
  62. _.each(items, function (item) {
  63. if (item) {
  64. var area = $(item.source[0]).attr('area');
  65. // determine if current selection is a valid selected area
  66. var isAreaSelected = _this2._isValidSelectedArea(item);
  67. // title Action/Slot action requirs the info as part of selectionContext
  68. if (isAreaSelected) {
  69. item.selectionContext = _this2._updateSelectionContext(item.selectionContext);
  70. }
  71. targets.push({
  72. key: item.key,
  73. type: item.infoType,
  74. source: item.source,
  75. values: item.values,
  76. selectionContext: item.selectionContext,
  77. area: area,
  78. isAreaSelected: isAreaSelected
  79. });
  80. }
  81. });
  82. return targets;
  83. };
  84. CrosstabEventTarget.prototype._isValidSelectedArea = function _isValidSelectedArea(item) {
  85. var $itemSource = item.source && item.source[0] && $(item.source[0]);
  86. if ($itemSource.hasClass('dashboard-grid-cell-selected')) {
  87. return $itemSource.attr('area') !== AREA_TYPE.SUMMARY;
  88. }
  89. };
  90. CrosstabEventTarget.prototype._updateSelectionContext = function _updateSelectionContext(selectionContext) {
  91. selectionContext = selectionContext || {};
  92. _.extend(selectionContext, {
  93. actions: {
  94. actionOptions: {
  95. TextAction: {
  96. isAreaSelected: true
  97. }
  98. }
  99. }
  100. });
  101. return selectionContext;
  102. };
  103. CrosstabEventTarget.prototype.decorateTarget = function decorateTarget(items, name, value, isMultiSelect) {
  104. var decorated = false;
  105. //crosstab does support style 'hightlight', it only decorate for style 'implied_selection' because this style supports muti-select cells
  106. if (name === 'highlight') {
  107. return true;
  108. } else if (name === 'implied_selection') {
  109. var visControl = this.view.visControl;
  110. if (items && items.length > 0) {
  111. var oSourceNode = items[0].source; //There will be only one items for crosstab
  112. if (oSourceNode) {
  113. var area = oSourceNode.attr('area');
  114. var isMeasureHeader = area === AREA_TYPE.MEASURE;
  115. var isSummary = area === AREA_TYPE.SUMMARY;
  116. if (isMeasureHeader) {
  117. if (value) {
  118. if (isMultiSelect) {
  119. visControl.decorateMeasureHeader(oSourceNode[0]);
  120. } else {
  121. // Measures header decorating
  122. this._clearSelectionController().then(function () {
  123. visControl.clearSelection({ clearSelectionCaches: true });
  124. visControl.decorateMeasureHeader(oSourceNode[0]);
  125. });
  126. }
  127. } else {
  128. // Clearing measure header decorations (items is undefined on hover)
  129. visControl.resetMeasureHeaderDecorations();
  130. }
  131. decorated = true;
  132. }
  133. if (isSummary) {
  134. if (value) {
  135. // Highlight summary cells
  136. this._clearSelectionController().then(function () {
  137. visControl.clearSelection({ clearSelectionCaches: true });
  138. visControl.highlightSummary(oSourceNode[0]);
  139. });
  140. } else {
  141. // Clearing summary cells highlighting
  142. visControl.resetSummaryHighlight();
  143. }
  144. decorated = true;
  145. }
  146. }
  147. } else if (!items) {
  148. // Clearing measure header decorations (items is undefined on hover)
  149. visControl.resetMeasureHeaderDecorations();
  150. visControl.resetSummaryHighlight();
  151. decorated = true;
  152. }
  153. }
  154. return decorated;
  155. };
  156. CrosstabEventTarget.prototype._clearSelectionController = function _clearSelectionController() {
  157. var visualization = this.content.getFeature('Visualization');
  158. var mappedSlotList = visualization.getSlots().getMappedSlotList();
  159. var itemIds = [];
  160. _.each(mappedSlotList, function (slot) {
  161. var dataItemList = slot.getDataItemList();
  162. if (dataItemList[0].getType() === 'category') {
  163. _.each(dataItemList, function (dataitem) {
  164. itemIds.push(dataitem.getColumnId());
  165. });
  166. }
  167. });
  168. var visController = this.content.getFeature('InteractivityController.deprecated');
  169. return visController.select({
  170. itemIds: itemIds,
  171. tuple: [],
  172. command: 'update',
  173. slotsToClear: mappedSlotList
  174. });
  175. };
  176. CrosstabEventTarget.prototype.remove = function remove() {
  177. this.ownerWidget = null;
  178. this.view = null;
  179. _NonVIPREventTarget.prototype.remove.call(this);
  180. };
  181. CrosstabEventTarget.prototype._getEventTargetItem = function _getEventTargetItem(event) {
  182. var target = this._getTargetNode(event);
  183. if (target && target.textContent) {
  184. var $eventTarget = $(target);
  185. var bIsCell = $eventTarget.attr('tuple');
  186. if (this.view.visControl.isCrosstaMeasureNodeSelected(target) || $eventTarget.attr('measure') === 'true') {
  187. return [this._getMeasureItemClassTarget(event)];
  188. } else if ($eventTarget.attr('area') === AREA_TYPE.SUMMARY) {
  189. return [this._getSummaryItemTarget(event, bIsCell)];
  190. } else {
  191. return bIsCell ? [this._getDatapointTarget(event)] : [this._getItemTarget(event)];
  192. }
  193. }
  194. };
  195. CrosstabEventTarget.prototype._getDatapointTarget = function _getDatapointTarget(event) {
  196. var oSelections = this.view.visControl.dataPointNodeToSlotsSelections(event);
  197. if (!oSelections) {
  198. return null;
  199. }
  200. var attributeSelections = oSelections.attributeSelections;
  201. var factSelections = [];
  202. if (oSelections.selectionContext) {
  203. // The selectionContext in a datapoint oSelection is the mapIndex of the data item that the datapoint corresponds to
  204. factSelections[oSelections.selectionContext] = oSelections.factSelections && oSelections.factSelections[0] ? oSelections.factSelections[0].value : [];
  205. } else {
  206. factSelections = oSelections.factSelections && oSelections.factSelections[0] ? [oSelections.factSelections[0].value] : [];
  207. }
  208. var aColumnValues = _.pluck(_.filter(attributeSelections, function (entry) {
  209. return entry.edgeType === CELL_TYPE.COLUMN;
  210. }), 'value');
  211. var aRowValues = _.pluck(_.filter(attributeSelections, function (entry) {
  212. return entry.edgeType === CELL_TYPE.ROW;
  213. }), 'value');
  214. var heatSelections = oSelections.factSelections && oSelections.factSelections[1] ? [oSelections.factSelections[1].value] : [];
  215. var oItem = this._createItem(EVENTTYPE.DATAPOINT, event);
  216. this._addItemValues(oItem.values, aColumnValues, aRowValues, factSelections, heatSelections);
  217. // Disable selection actions for events containing expanded items
  218. // This is due to limitations for brushing/slicing on expanded items for expand/collapse feature
  219. if (this._includesExpanded(aColumnValues, aRowValues)) {
  220. oItem.infoType = EVENTTYPE.EXPANDED;
  221. oItem.values = [];
  222. $(event.currentTarget).addClass('hoverExpanded');
  223. } else {
  224. $(event.currentTarget).removeClass('hoverExpanded');
  225. }
  226. return oItem;
  227. };
  228. CrosstabEventTarget.prototype._getItemTarget = function _getItemTarget(event) {
  229. var oSelections = this.view.visControl.nodeToSelection(event);
  230. if (!oSelections) {
  231. return null;
  232. }
  233. var aColumnValues = oSelections.column_level1 ? oSelections.column_level1.value : [];
  234. var aRowValues = oSelections.row_level1 ? oSelections.row_level1.value : [];
  235. var aFactValues = oSelections.datapoint ? [oSelections.datapoint] : [];
  236. var aItemClassValues = oSelections.itemClassValues ? oSelections.itemClassValues : [];
  237. var sType = oSelections.isInnerEdge === true ? EVENTTYPE.DATAPOINT : EVENTTYPE.ITEM;
  238. var oItem = this._createItem(sType, event);
  239. // If itemClass target, obtain the item values first. The items are then used to create
  240. // the selection context in _getMeasureSelectionContext
  241. if (aItemClassValues.length > 0) {
  242. oItem.values = aItemClassValues;
  243. oItem.selectionContext = this._getMeasureSelectionContext(oItem.values);
  244. } else {
  245. var oSelectionContext = this._getSelectionContext(oSelections.selectionContext);
  246. if (oSelectionContext) {
  247. oItem.selectionContext = oSelectionContext;
  248. oItem.selectionContext.actions.actionOptions = {
  249. deleteAction: { excludeAction: true },
  250. jumpToAction: { area: event.target.getAttribute('area') }
  251. };
  252. }
  253. this._addItemValues(oItem.values, aColumnValues, aRowValues, aFactValues);
  254. }
  255. // Disable selection actions for events containing expanded items
  256. // This is due to limitations for brushing/slicing on expanded items for expand/collapse feature
  257. if (this._includesExpanded(aColumnValues, aRowValues)) {
  258. oItem.infoType = EVENTTYPE.EXPANDED;
  259. oItem.values = [];
  260. $(event.currentTarget).addClass('hoverExpanded');
  261. } else {
  262. $(event.currentTarget).removeClass('hoverExpanded');
  263. }
  264. return oItem;
  265. };
  266. CrosstabEventTarget.prototype._getMeasureSelectionContext = function _getMeasureSelectionContext(oItemValues) {
  267. var selectionContext = {
  268. actions: { actionsToKeep: [], actionOptions: {} }
  269. };
  270. selectionContext.slots = [this.visualization.getSlots().getSlot(SLOTID.VALUES)];
  271. selectionContext.mapIndex = [];
  272. _.each(oItemValues, function (slot) {
  273. _.each(slot, function (dataItem) {
  274. selectionContext.mapIndex.push(dataItem.mapIndex);
  275. });
  276. });
  277. return selectionContext;
  278. };
  279. CrosstabEventTarget.prototype._getSelectionContext = function _getSelectionContext(selectionContext) {
  280. if (selectionContext.level === undefined) {
  281. return null;
  282. }
  283. var oSlot = this.visualization.getSlots().getSlot(selectionContext.slotID);
  284. var aColumnItemAPIs = oSlot && oSlot.getDataItemList();
  285. if (aColumnItemAPIs && aColumnItemAPIs.length > 0 && selectionContext.level < aColumnItemAPIs.length) {
  286. return {
  287. 'mapIndex': selectionContext.level,
  288. 'slots': [oSlot],
  289. 'actions': { actionsToKeep: [], actionOptions: {} }
  290. };
  291. }
  292. };
  293. CrosstabEventTarget.prototype._createItem = function _createItem(itemType, event) {
  294. var oItem = {};
  295. oItem.infoType = itemType;
  296. var $target = $(this._getTargetNode(event));
  297. oItem.key = $target.attr('row') + ':' + $target.attr('col');
  298. oItem.source = $target;
  299. oItem.values = [];
  300. return oItem;
  301. };
  302. CrosstabEventTarget.prototype._addItemValues = function _addItemValues(itemValues, colValues, rowValues, factValues, heatValues) {
  303. var aSlots = this.visualization.getSlots().getMappedSlotList(); //Mapped Slots only
  304. _.each(aSlots, function (entry) {
  305. var id = entry.getId();
  306. if (id === SLOTID.COLUMN) {
  307. itemValues.push(colValues);
  308. } else if (id === SLOTID.ROW) {
  309. itemValues.push(rowValues); //Required Slot
  310. } else if (id === SLOTID.VALUES) {
  311. itemValues.push(factValues); //Required Slot
  312. } else if (id === SLOTID.HEAT) {
  313. itemValues.push(heatValues);
  314. }
  315. });
  316. };
  317. CrosstabEventTarget.prototype._getMeasureItemClassTarget = function _getMeasureItemClassTarget(event) {
  318. var itemTarget = this._getItemTarget(event);
  319. itemTarget.infoType = EVENTTYPE.ITEMCLASS;
  320. return itemTarget;
  321. };
  322. CrosstabEventTarget.prototype._getSummaryItemTarget = function _getSummaryItemTarget(event, isCell) {
  323. var itemTarget = isCell ? null : this._getItemTarget(event);
  324. if (itemTarget) {
  325. itemTarget.infoType = EVENTTYPE.SUMMARY;
  326. itemTarget.selectionContext = {
  327. actions: {
  328. actionsToKeep: ['text'],
  329. actionOptions: {
  330. TextAction: {
  331. area: AREA_TYPE.SUMMARY
  332. }
  333. }
  334. }
  335. };
  336. }
  337. return itemTarget;
  338. };
  339. CrosstabEventTarget.prototype._getUnionValues = function _getUnionValues() {
  340. var dataItems = this.view.content.getFeature('Visualization').getSlots().getDataItemList();
  341. var drillDownValue = void 0;
  342. var unionItems = [];
  343. var drillDownValues = [];
  344. // Get first level union item list and slot drill down values
  345. _.forEach(dataItems, function (dataItem) {
  346. drillDownValue = dataItem.getDrillDownValue();
  347. if (drillDownValue) {
  348. drillDownValues.push(drillDownValue);
  349. }
  350. if (dataItem.getUnion) {
  351. unionItems.push.apply(unionItems, dataItem.getUnion().getDataItemList());
  352. }
  353. });
  354. var item = void 0;
  355. var values = [];
  356. // DFS on union model
  357. while (!_.isEmpty(unionItems)) {
  358. item = unionItems.pop();
  359. drillDownValue = item.getDrillDownValue();
  360. if (drillDownValue && !(_.indexOf(drillDownValues, drillDownValue) !== -1)) {
  361. values.push(drillDownValue);
  362. }
  363. if (item.getUnion) {
  364. unionItems.push.apply(unionItems, item.getUnion().getDataItemList());
  365. }
  366. }
  367. return values;
  368. };
  369. CrosstabEventTarget.prototype._includesExpanded = function _includesExpanded(aColumnValues, aRowValues) {
  370. var eventValues = [];
  371. // value.pu is for level based hiearchy; value.p.u is for member based hierachy
  372. eventValues.push.apply(eventValues, aColumnValues.reduce(function (arr, value) {
  373. if (value.pu) {
  374. arr.push(value.pu);
  375. } else if (value.p && value.p.u) {
  376. arr.push(value.p.u);
  377. }
  378. return arr;
  379. }, []));
  380. eventValues.push.apply(eventValues, aRowValues.reduce(function (arr, value) {
  381. if (value.pu) {
  382. arr.push(value.pu);
  383. } else if (value.p && value.p.u) {
  384. arr.push(value.p.u);
  385. }
  386. return arr;
  387. }, []));
  388. var unionValues = this._getUnionValues();
  389. return !_.isEmpty(_.intersection(eventValues, unionValues));
  390. };
  391. CrosstabEventTarget.prototype._isValidEvent = function _isValidEvent(event) {
  392. var _this3 = this;
  393. var _isTargetValidGridCell = function _isTargetValidGridCell(eventTarget) {
  394. return eventTarget.localName === 'div' && ($(eventTarget).hasClass('bottom-right-grid-cell') || $(eventTarget).hasClass('top-right-grid-cell') || $(eventTarget).hasClass('bottom-left-grid-cell') || $(eventTarget).hasClass('top-left-grid-cell'));
  395. };
  396. var _fnClickTapCheck = function _fnClickTapCheck(eventTarget) {
  397. return _isTargetValidGridCell(eventTarget);
  398. };
  399. var _fnContextMenuCheck = function _fnContextMenuCheck(eventTarget) {
  400. return _isTargetValidGridCell(eventTarget);
  401. };
  402. var _fnMouseMoveCheck = function _fnMouseMoveCheck(eventTarget) {
  403. return _isTargetValidGridCell(eventTarget);
  404. };
  405. var _fnMouseLeaveCheck = function _fnMouseLeaveCheck(eventTarget) {
  406. return _this3.mouseWithinBoundCheck(event) && _isTargetValidGridCell(eventTarget);
  407. };
  408. var _fnKeydownCheck = function _fnKeydownCheck(eventTarget) {
  409. if (_isTargetValidGridCell(eventTarget)) {
  410. return true;
  411. }
  412. return false;
  413. };
  414. var oValidEvents = {
  415. click: _fnClickTapCheck,
  416. clicktap: _fnClickTapCheck,
  417. mousedown: _fnClickTapCheck,
  418. tap: _fnClickTapCheck,
  419. contextmenu: _fnContextMenuCheck,
  420. hold: _fnContextMenuCheck,
  421. mousemove: _fnMouseMoveCheck,
  422. mouseleave: _fnMouseLeaveCheck.bind(this),
  423. keydown: _fnKeydownCheck
  424. };
  425. var fnCheck = oValidEvents[event.type];
  426. var target = this._getTargetNode(event);
  427. return fnCheck && fnCheck(target) === true;
  428. };
  429. return CrosstabEventTarget;
  430. }(NonVIPREventTarget);
  431. return CrosstabEventTarget;
  432. });
  433. //# sourceMappingURL=CrosstabEventTarget.js.map