VIPREventTarget.js 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792
  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. *+------------------------------------------------------------------------+
  7. *| Licensed Materials - Property of IBM
  8. *| IBM Cognos Products: Dashboard
  9. *| (C) Copyright IBM Corp. 2017, 2020
  10. *|
  11. *| US Government Users Restricted Rights - Use, duplication or disclosure
  12. *| restricted by GSA ADP Schedule Contract with IBM Corp.
  13. *+------------------------------------------------------------------------+
  14. */
  15. define(['jquery', '../common/EventTarget', '../../../apiHelpers/SlotAPIHelper', 'underscore', '../VisEventHandler', '../../vipr/VIPRUtils', '../../../lib/@waca/core-client/js/core-client/utils/BrowserUtils', '../../vipr/data/VIPRCatContDataItem', './VIPRDataPointSummarizer'], function ($, EventTarget, SlotAPIHelper, _, VisEventHandler, VIPRUtils, BrowserUtils, VIPRCatContDataItem, VIPRDataPointSummarizer) {
  16. var ZOOM_VELOCITY = 0.002;
  17. var TOUCHMARGIN = 1;
  18. var VIPRTYPE = {
  19. CUSTOMDATA: 'customdata',
  20. DATAPOINT: 'datapoint',
  21. ITEMCLASS: 'itemclass',
  22. ITEM: 'item',
  23. DATAITEM: 'dataitem',
  24. TUPLE: 'tuple',
  25. VALUE: 'value',
  26. INVALID: null,
  27. EMPTY: 'empty'
  28. };
  29. var CUSTOMDATATYPE = {
  30. KEYDRIVERSHOW: 'keydriver_show',
  31. DRIVERINFO: 'driverinfo',
  32. TREENODEINFO: 'treenodeinfo'
  33. };
  34. var VIPRDATAPOINTTYPE = {
  35. VALUE: 'value',
  36. TUPLE: 'tuple'
  37. };
  38. var VIPREventTarget = function (_EventTarget) {
  39. _inherits(VIPREventTarget, _EventTarget);
  40. function VIPREventTarget() {
  41. var _ret;
  42. _classCallCheck(this, VIPREventTarget);
  43. for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
  44. args[_key] = arguments[_key];
  45. }
  46. var _this = _possibleConstructorReturn(this, _EventTarget.call.apply(_EventTarget, [this].concat(args)));
  47. var options = args[0] || {};
  48. _this.viprWidget = options.viprWidget;
  49. _this.viprInteractivity = _this.viprWidget.getInteractivity();
  50. // map from visDecorations to viprDecoration
  51. _this.viprDecorations = {};
  52. _this.viprDecorations[VisEventHandler.DECORATIONS.HIGHLIGHT] = 'highlighted';
  53. _this.viprDecorations[VisEventHandler.DECORATIONS.SELECT] = 'selected';
  54. _this.viprDecorations[VisEventHandler.DECORATIONS.TOOLTIP] = 'tooltip';
  55. _this.viprDataPointSummarizer = new VIPRDataPointSummarizer(_this.visualization);
  56. return _ret = _this.getAPI(), _possibleConstructorReturn(_this, _ret);
  57. }
  58. /**
  59. * remove viprWidget from event
  60. */
  61. VIPREventTarget.prototype.remove = function remove() {
  62. this.viprWidget = null;
  63. _EventTarget.prototype.remove.call(this);
  64. };
  65. /**
  66. * @override
  67. * Determine whether visualization state (ie. zoom, pan, scroll) can be restored
  68. * @return {boolean} true if the visualization state can be restored, otherwise false
  69. */
  70. VIPREventTarget.prototype.canRestore = function canRestore() {
  71. // state can be restore if
  72. // 1. interactivityState property is supportedAND
  73. // 2. autoZoom is disabled
  74. return VIPRUtils.isPropertyIncluded(this.visualization.getDefinition().getId(), 'interactivityState') && !this.content.getPropertyValue('autoZoom');
  75. };
  76. /**
  77. * @override
  78. * Restore the visualization state
  79. * @param {Object} state object containing the state of the visualization
  80. */
  81. VIPREventTarget.prototype.restore = function restore(state) {
  82. if (state && this.canRestore()) {
  83. this.viprWidget.setState(state);
  84. }
  85. };
  86. /**
  87. * Get the array of event targets based on the event.
  88. * Event target represents a data point object that corresponds to the event.
  89. * NOTES:
  90. * Legend Titles are of type VIPRTYPE.DATAITEM which contain entries of type VIPRTYPE.TUPLE (note: 1 DATAITEM/TUPLE is returned for stacked legends)
  91. * Axis Titles are of type VIPRTYPE.ITEMCLASS which contain entries of type VIPRTYPE.ITEM (note: n ITEMCLASSES/ITEMS are returned for stacked axes.)
  92. * Chart elements (eg bubbles) are of type VIPRTYPE.DATAPOINT
  93. *
  94. * @param event Event object
  95. */
  96. VIPREventTarget.prototype.getEventTargets = function getEventTargets(event, radius) {
  97. var clientX = this._getClientX(event);
  98. var clientY = this._getClientY(event);
  99. var visCoord = this.viprWidget.getVisCoordinate(clientX, clientY);
  100. var items = this.viprWidget.getItemsAtPoint(visCoord, radius);
  101. // for mobile events, we make a square around the event coords and return the items inside the square
  102. // if nothing was found - consider moving the isIPad check to visEventHandler in the future.
  103. if ((!items || items.length === 0) && BrowserUtils.isIPad()) {
  104. var coords = this._inflateCoordinates(clientX, clientY);
  105. return this.getTargetsByCords(coords, false);
  106. } else {
  107. var options = {
  108. visCoord: visCoord
  109. };
  110. return this._processItems(items, options);
  111. }
  112. };
  113. VIPREventTarget.prototype._inflateCoordinates = function _inflateCoordinates(clientX, clientY) {
  114. return [{ x: clientX - TOUCHMARGIN, y: clientY - TOUCHMARGIN }, { x: clientX + TOUCHMARGIN, y: clientY - TOUCHMARGIN }, { x: clientX + TOUCHMARGIN, y: clientY + TOUCHMARGIN }, { x: clientX - TOUCHMARGIN, y: clientY + TOUCHMARGIN }];
  115. };
  116. VIPREventTarget.prototype.getTargetsByCords = function getTargetsByCords(cords, summarize) {
  117. var targets;
  118. var visCords = cords.map(function (cord) {
  119. return this.viprWidget.getVisCoordinate(cord.x, cord.y);
  120. }.bind(this));
  121. var items = this.viprWidget.getItemsInPolygon(visCords);
  122. var options = {
  123. summarize: summarize,
  124. visCoord: visCords
  125. };
  126. targets = this._processItems(items, options);
  127. return targets;
  128. };
  129. /**
  130. * @override
  131. * Get the axis items from event and offset
  132. * @param event - the event as generated by visEventHandler
  133. * @param offset - an optional offset (in pixels) to ensure the line does not become the target of selections etc.
  134. * @return {object} The axis items
  135. */
  136. VIPREventTarget.prototype.getValuesAtPoint = function getValuesAtPoint(event, offset) {
  137. if (this.viprWidget && this.viprWidget.getVisCoordinate) {
  138. var eventOffset = offset || 0;
  139. var coord = this.viprWidget.getVisCoordinate(event.clientX + eventOffset, event.clientY - eventOffset);
  140. return this.viprWidget.getAxisItemsAtPoint(coord);
  141. }
  142. };
  143. /**
  144. * Visually decorate the targets.
  145. *
  146. * @param targets Event targets
  147. * @param visDecorationName Decoration name (ie. highlight, select)
  148. * @return true if target has been decorated, otherwise false
  149. */
  150. VIPREventTarget.prototype.decorateTarget = function decorateTarget(targets, visDecorationName, value) {
  151. var decorated = false;
  152. var viprDecorationName = this.viprDecorations[visDecorationName];
  153. if (viprDecorationName) {
  154. _.each(targets, function (target) {
  155. if (target.source && typeof target.source.decorate === 'function') {
  156. target.source.decorate(viprDecorationName, value);
  157. decorated = true;
  158. } else if (target.type === 'customdata') {
  159. // custom data decoration is handled by applyCustomDataSelection
  160. decorated = true;
  161. }
  162. });
  163. }
  164. return decorated;
  165. };
  166. /**
  167. * Obtain the decoration value from the given target item and decoration name
  168. * @param item event target item containing the decoration
  169. * @param decorationName common decoration name defined by VisEventHandler.DECORATIONS
  170. */
  171. VIPREventTarget.prototype.getDecoration = function getDecoration(item, decorationName) {
  172. var viprDecorationName = this.viprDecorations[decorationName];
  173. if (viprDecorationName && item.source && typeof item.source.hasDecoration === 'function' && typeof item.source.getDecoration === 'function' && item.source.hasDecoration(viprDecorationName)) {
  174. return item.source.getDecoration(viprDecorationName);
  175. }
  176. };
  177. /**
  178. * Complete the series of decorations.
  179. * After clearing and adding multiple decorations, complete the decorations by rendering the visualization.
  180. */
  181. VIPREventTarget.prototype.completeDecorations = function completeDecorations() {
  182. this.viprWidget.render('client');
  183. };
  184. /**
  185. * Apply selection on customdata target.
  186. *
  187. * @param {ArrayOfObject} targets Event targets
  188. */
  189. VIPREventTarget.prototype.applyCustomDataSelection = function applyCustomDataSelection(targets, options) {
  190. var target = _.isArray(targets) ? targets[0] : targets; //Sample the targets
  191. // target is empty when all decorations needs to be cleared
  192. // otherwise the decorating target item type needs to be customdata
  193. if (!target || target.type === VIPRTYPE.CUSTOMDATA && !this._isLengendAndEncodingPayload(target)) {
  194. //todo: need to make custom data decoration consistent with other data;
  195. this._handleCustomDataDecorations(targets, options);
  196. }
  197. };
  198. //TODO: post Endor R1, we will remove this check and re-enable Comet Chart Legend integration
  199. VIPREventTarget.prototype._isLengendAndEncodingPayload = function _isLengendAndEncodingPayload(item) {
  200. if (item.area === 'legend' && item.values && item.values.length === 1) {
  201. var payload = item.values[0].payload;
  202. return payload && payload.type === 'encoding';
  203. }
  204. return false;
  205. };
  206. /**
  207. * Return the list of custom data selections in label/value pair
  208. * @param {Object} target event target item of the selected custom data
  209. */
  210. VIPREventTarget.prototype.getCustomDataSelections = function getCustomDataSelections(target) {
  211. var selections = [];
  212. if (target) {
  213. _.each(target.values, function (value) {
  214. var tooltip = value.payload && value.payload.tooltip;
  215. if (tooltip) {
  216. // append the name/value pairs
  217. if (tooltip.getLines) {
  218. var lines = tooltip.getLines();
  219. if (lines && lines.length > 0) {
  220. selections.push.apply(selections, tooltip.getLines());
  221. }
  222. }
  223. // only has generated string caption value without a name/value pair
  224. if (tooltip.getCaption) {
  225. var caption = tooltip.getCaption();
  226. if (caption) {
  227. selections.push({
  228. value: caption
  229. });
  230. }
  231. }
  232. }
  233. });
  234. }
  235. return selections;
  236. };
  237. /**
  238. * Determine whether the given interactivity state should be handled
  239. * @param {Object} state visualization interactivity state
  240. * @return visualization interactivity state if it's supported, otherwise false
  241. */
  242. VIPREventTarget.prototype._handleInteractivityState = function _handleInteractivityState(state) {
  243. return VIPRUtils.isPropertyIncluded(this.visualization.getDefinition().getId(), 'interactivityState') ? state : undefined;
  244. };
  245. /**
  246. * Determine whether the vipr visualization supports pan and zoom
  247. */
  248. VIPREventTarget.prototype.canZoom = function canZoom() {
  249. return this.viprInteractivity ? this.viprInteractivity.canZoom() : false;
  250. };
  251. /**
  252. * Start the zooming session with the VIPR visualization
  253. *
  254. * @param event Event object
  255. */
  256. VIPREventTarget.prototype.zoomStart = function zoomStart(event) {
  257. if (this.viprInteractivity) {
  258. try {
  259. // in case of a two touch gesture zoom, use the center coordinates of the hammer gesture event
  260. var coordinates = event.gesture ? event.gesture.center : event;
  261. var visCoord = this.viprWidget.getVisCoordinate(this._getClientX(coordinates), this._getClientY(coordinates));
  262. this.viprInteractivity.startInteractivity(visCoord);
  263. // initialize the gesture scale to 1 as we start zoom
  264. this.gestureScale = 1;
  265. } catch (err) {
  266. console.warn(err);
  267. }
  268. }
  269. };
  270. /**
  271. * Apply zoom to the VIPR visualization
  272. *
  273. * @param event Event object
  274. */
  275. VIPREventTarget.prototype.zoom = function zoom(event) {
  276. if (this.viprInteractivity) {
  277. try {
  278. // in case of a two touch gesture zoom, use the center coordinates of the hammer gesture event
  279. var coordinates = event.gesture ? event.gesture.center : event;
  280. var visCoord = this.viprWidget.getVisCoordinate(this._getClientX(coordinates), this._getClientY(coordinates));
  281. var scale = this._getZoomScale(event);
  282. this.viprInteractivity.zoom(visCoord, scale);
  283. } catch (err) {
  284. console.warn(err);
  285. }
  286. }
  287. };
  288. /**
  289. * End the zooming session with the VIPR visualization
  290. *
  291. * @param event Event object
  292. * @returns {Object|undefined} interactivity state containing the zoom level OR undefined if state is not supported
  293. */
  294. VIPREventTarget.prototype.zoomEnd = function zoomEnd(event) {
  295. if (this.viprInteractivity) {
  296. try {
  297. // in case of a two touch gesture zoom, use the center coordinates of the hammer gesture event
  298. var coordinates = event.gesture ? event.gesture.center : event;
  299. var visCoord = this.viprWidget.getVisCoordinate(this._getClientX(coordinates), this._getClientY(coordinates));
  300. this.viprInteractivity.endInteractivity(visCoord);
  301. // disable the gesture scale as we end zoom
  302. this.gestureScale = 0;
  303. return this._handleInteractivityState(this.viprWidget.getState());
  304. } catch (err) {
  305. console.warn(err);
  306. }
  307. }
  308. };
  309. /**
  310. * Start the panning session with VIPR visualization
  311. *
  312. * @param event Event object
  313. */
  314. VIPREventTarget.prototype.panStart = function panStart(event) {
  315. if (this.viprInteractivity) {
  316. try {
  317. var visCoord = this.viprWidget.getVisCoordinate(this._getClientX(event), this._getClientY(event));
  318. this.viprInteractivity.startInteractivity(visCoord);
  319. } catch (err) {
  320. console.warn(err);
  321. }
  322. }
  323. };
  324. /**
  325. * Apply panning to the VIPR visualization
  326. *
  327. * @param event Event object
  328. */
  329. VIPREventTarget.prototype.pan = function pan(event) {
  330. if (this.viprInteractivity) {
  331. try {
  332. var visCoord = this.viprWidget.getVisCoordinate(this._getClientX(event), this._getClientY(event));
  333. this.viprInteractivity.translate(visCoord);
  334. } catch (err) {
  335. console.warn(err);
  336. }
  337. }
  338. };
  339. /**
  340. * End the panning session with VIPR visualization
  341. *
  342. * @param event Event object
  343. * @returns {Object|undefined} interactivity state containing the pan OR undefined if state is not supported
  344. */
  345. VIPREventTarget.prototype.panEnd = function panEnd(event) {
  346. if (this.viprInteractivity) {
  347. try {
  348. var visCoord = this.viprWidget.getVisCoordinate(this._getClientX(event), this._getClientY(event));
  349. this.viprInteractivity.endInteractivity(visCoord);
  350. return this._handleInteractivityState(this.viprWidget.getState());
  351. } catch (err) {
  352. console.warn(err);
  353. }
  354. }
  355. };
  356. VIPREventTarget.prototype.processKeyDown = function processKeyDown() {
  357. return false;
  358. };
  359. /**
  360. * @private
  361. * @function _getClientX
  362. * Get the clientX property from the given event
  363. * @param {Object} event - the event object
  364. * @returns clientX value of the event
  365. */
  366. VIPREventTarget.prototype._getClientX = function _getClientX(event) {
  367. return event.hasOwnProperty('clientX') ? event.clientX : event.originalEvent.clientX;
  368. };
  369. /**
  370. * @private
  371. * @function __getClientY
  372. * Get the clientY property from the given event
  373. * @param {Object} event - the event object
  374. * @returns clientY value of the event
  375. */
  376. VIPREventTarget.prototype._getClientY = function _getClientY(event) {
  377. return event.hasOwnProperty('clientY') ? event.clientY : event.originalEvent.clientY;
  378. };
  379. VIPREventTarget.prototype._processItems = function _processItems(items, options) {
  380. var _this2 = this;
  381. var targets;
  382. var summarize = options.summarize;
  383. var visCoord = options.visCoord;
  384. switch (this._getTargetType(items)) {
  385. case VIPRTYPE.DATAPOINT:
  386. {
  387. var shouldDataItemsSummarize = VIPRUtils.doesConfigPropertyMatchExpected(this.visualization.getDefinition().getId(), 'shouldMultiPointSelectionSummarize', true);
  388. targets = this._processDataPointTargets(items, summarize || shouldDataItemsSummarize);
  389. break;
  390. }
  391. case VIPRTYPE.VALUE:
  392. targets = this._processValueTargets(items);
  393. break;
  394. case VIPRTYPE.ITEM:
  395. case VIPRTYPE.TUPLE:
  396. targets = this._processTupleItemTargets(items);
  397. break;
  398. case VIPRTYPE.ITEMCLASS:
  399. case VIPRTYPE.DATAITEM:
  400. targets = this._processDataItemClassTargets(items);
  401. break;
  402. case VIPRTYPE.CUSTOMDATA:
  403. targets = this._processCustomDataTargets(items);
  404. break;
  405. case VIPRTYPE.EMPTY:
  406. targets = [];
  407. break;
  408. // invalid or unknown target
  409. case VIPRTYPE.INVALID:
  410. default:
  411. targets = null;
  412. }
  413. _.each(targets, function (target) {
  414. // Attach the clicked area to the target. The area could be of values: visualization, legend, or none
  415. if (visCoord && visCoord.area) {
  416. target.area = visCoord.area;
  417. target.selectionContext = {
  418. actions: {
  419. actionOptions: { TextAction: { area: visCoord.area } }
  420. }
  421. };
  422. }
  423. // add datasetId;
  424. target.datasetId = _this2._datasetId(target);
  425. });
  426. return targets;
  427. };
  428. VIPREventTarget.prototype._getTargetType = function _getTargetType(items) {
  429. if (!items) {
  430. return VIPRTYPE.INVALID;
  431. }
  432. return items.length > 0 ? items[0].infoType : VIPRTYPE.EMPTY;
  433. };
  434. VIPREventTarget.prototype._processValueTargets = function _processValueTargets(items) {
  435. var targets = [];
  436. _.each(items, function (item) {
  437. var valueObj = item.source;
  438. var slotIndex = valueObj.getIndex();
  439. // build a sparse values array
  440. // this allows re-using the existing datapoint mechanism with values
  441. var values = [];
  442. values[slotIndex] = [item.value];
  443. targets.push({
  444. key: 'value_' + slotIndex,
  445. type: VIPRTYPE.DATAPOINT,
  446. source: valueObj,
  447. values: values
  448. });
  449. });
  450. return targets;
  451. };
  452. VIPREventTarget.prototype._processDataPointTargets = function _processDataPointTargets(items, summarize) {
  453. var _this3 = this;
  454. var targets = [];
  455. summarize = typeof summarize === 'undefined' ? true : summarize;
  456. //The first slot in a selection is its topmost layer in the selection (the selectedLayer).
  457. //The datapoint target will be for that layer.
  458. var selectedLayer = null;
  459. _.each(items, function (item) {
  460. var slotAPIs = _this3._getSlotAPIsForItem(item);
  461. var slotLayer = slotAPIs && slotAPIs[0].getDefinition().getDatasetIdList()[0];
  462. if (!selectedLayer || slotLayer === selectedLayer) {
  463. selectedLayer = slotLayer;
  464. targets.push({
  465. key: item.key + ':' + slotLayer,
  466. type: VIPRTYPE.DATAPOINT,
  467. source: item.source,
  468. values: _this3._itemRowToTargetValues(item.row),
  469. slotAPIs: slotAPIs,
  470. onlyGlobalActions: _this3._isForecastData(item.source)
  471. });
  472. }
  473. });
  474. // Summarize multiple datapoint targets (area chart)
  475. if (targets.length && summarize) {
  476. //TODO: Temporarily wire of summarize dataPoint targets.
  477. targets = this.viprDataPointSummarizer.summarizeDataPointTargets(targets);
  478. }
  479. return targets;
  480. };
  481. VIPREventTarget.prototype._getSlotAPIsForItem = function _getSlotAPIsForItem(item) {
  482. var slotAPIs = item.source && item.source.dataset && item.source.dataset.slotAPIs;
  483. if (!slotAPIs && item.source && item.source.dataset) {
  484. // the latest implementation of VIPRData does not supply the SlotAPIs
  485. // this is rather intentional, and can rather provide the id of the source dataset
  486. // @todo this needs to be revised so that the EventTargets simply returns a datasetId, not the list of SlotAPIs
  487. slotAPIs = SlotAPIHelper.getMappedSlotListByDataset(this.visualization, item.source.dataset.getId());
  488. }
  489. if (slotAPIs && this._isForecastData(item.source)) {
  490. return slotAPIs.map( //Position of each slot matters, but we don't want numerical slots, so replace them with null
  491. function (slot) {
  492. return slot.getDataItemList().find(function (dataItem) {
  493. return dataItem.getType() === 'fact';
  494. }) ? null : slot;
  495. });
  496. }
  497. return slotAPIs;
  498. };
  499. VIPREventTarget.prototype._datasetId = function _datasetId(item) {
  500. return item && item.source && item.source.dataset && item.source.dataset.getId && item.source.dataset.getId();
  501. };
  502. //This function is called for both VIPRTYPE.ITEM and VIPRTYPE.TUPLE
  503. //VIPRTYPE.ITEM corresponds to elements such as axis labels (eg in a bar chart)
  504. //When axis labels are stacked, there will be n items of type VIPRTYPE.ITEM
  505. //VIPRTYPE.TUPLE corresponds to elements such as legend labels (type VIPRTYPE.TUPLE).
  506. VIPREventTarget.prototype._processTupleItemTargets = function _processTupleItemTargets(items) {
  507. var _this4 = this;
  508. var targets = [];
  509. _.each(items, function (item) {
  510. var source = item.source;
  511. var onlyGlobalActions = false;
  512. if (source.datapoints && source.datapoints.length > 0) {
  513. onlyGlobalActions = _this4._isForecastData(source.datapoints[0]) || false;
  514. }
  515. if (source) {
  516. targets.push({
  517. key: item.key || item.getUniqueName(),
  518. type: VIPRTYPE.ITEM,
  519. source: source,
  520. values: _this4.viprDataPointSummarizer.summarizeDataPointValues(source.datapoints, source.indexes.dataitem, source),
  521. isEdgeSelect: true,
  522. onlyGlobalActions: onlyGlobalActions
  523. });
  524. }
  525. });
  526. if (items.length > 1) {
  527. targets = this._mergeTupleItemTargets(targets);
  528. }
  529. return targets;
  530. };
  531. VIPREventTarget.prototype._processDataItemClassTargets = function _processDataItemClassTargets(items) {
  532. var _this5 = this;
  533. var targets = [];
  534. _.each(items, function (item) {
  535. var values = [];
  536. var slotIds = _.map(_this5.visualization.getSlots().getMappedSlotList(), function (slot) {
  537. return slot.getId();
  538. });
  539. var slotIndex = slotIds.indexOf(item.slotDef.name);
  540. if (slotIndex > -1) {
  541. values[slotIndex] = [{
  542. u: item.source.getUniqueName(),
  543. d: item.source.getCaption()
  544. }];
  545. targets.push({
  546. key: item.source.getUniqueName(),
  547. type: VIPRTYPE.ITEMCLASS,
  548. source: item.source,
  549. values: values
  550. });
  551. }
  552. });
  553. return targets;
  554. };
  555. VIPREventTarget.prototype._processCustomDataTargets = function _processCustomDataTargets(items) {
  556. var targets = [];
  557. _.each(items, function (item) {
  558. targets.push({
  559. key: item.id,
  560. type: item.infoType,
  561. source: {},
  562. values: [{ payload: item.payload, customType: item.type }]
  563. });
  564. });
  565. return targets;
  566. };
  567. VIPREventTarget.prototype._itemRowToTargetValues = function _itemRowToTargetValues(row) {
  568. var targetValues = [];
  569. if (row) {
  570. row.forEach(function (data, indexInRow) {
  571. if (data.infoType === VIPRDATAPOINTTYPE.VALUE) {
  572. // Don't assume that the indexInRow is the same as the slot index
  573. // there could be a slot that contains multiple dataitems
  574. // We get the slot index from dataItem.indexes.dataitem
  575. var slotIndex = data.dataItem && data.dataItem.source && data.dataItem.source.indexes && data.dataItem.source.indexes.dataitem;
  576. if (slotIndex == null) {
  577. // not sure if we would ever run into this.. but just in case we have scenarios where the slots index is not found
  578. slotIndex = indexInRow;
  579. }
  580. if (!targetValues[slotIndex]) {
  581. targetValues[slotIndex] = [];
  582. }
  583. var values = targetValues[slotIndex];
  584. var multiMeasureSeries = _.find(row, function (data) {
  585. return data.key && data.key.indexOf(SlotAPIHelper.MULTI_MEASURES_SERIES) === 0;
  586. });
  587. var index = multiMeasureSeries ? multiMeasureSeries.index : values.length;
  588. if (data.dataItem && data.dataItem.source instanceof VIPRCatContDataItem) {
  589. values[index] = {
  590. u: data.value,
  591. d: data.value
  592. };
  593. } else {
  594. // if possible, use the raw data
  595. values[index] = data.source && data.source.getRawValue ? data.source.getRawValue() : data.value;
  596. }
  597. } else {
  598. targetValues[indexInRow] = _.map(data.items, function (catItem) {
  599. return {
  600. u: catItem.source.item.u,
  601. d: catItem.source.item.d,
  602. p: catItem.source.item.p
  603. };
  604. });
  605. }
  606. });
  607. }
  608. return targetValues;
  609. };
  610. /**
  611. * Merge the multiple nested tuple items to one target
  612. */
  613. VIPREventTarget.prototype._mergeTupleItemTargets = function _mergeTupleItemTargets(prevTargets) {
  614. var params = [true, {}];
  615. return [$.extend.apply($, params.concat(prevTargets))];
  616. };
  617. VIPREventTarget.prototype._handleCustomDataDecorations = function _handleCustomDataDecorations(items, options) {
  618. var decorations = [];
  619. // Decorate all items found under the pointer
  620. _.chain(items).pluck('values').flatten().each(function (value) {
  621. if (_.contains(CUSTOMDATATYPE, value.customType)) {
  622. decorations.push({
  623. id: value.payload.id,
  624. value: true
  625. });
  626. }
  627. });
  628. this.visAPI.setCustomDataDecoration('selected', decorations, options);
  629. };
  630. /**
  631. * Get the zoom scale from the event
  632. */
  633. VIPREventTarget.prototype._getZoomScale = function _getZoomScale(event) {
  634. if (event.gesture) {
  635. // default the gesture scale to 1 as we start zoom
  636. var previousScale = this.gestureScale || 1;
  637. // update the previous gesture scale
  638. this.gestureScale = event.gesture.scale;
  639. // calculate gesture zoom scale
  640. return event.gesture.scale / previousScale;
  641. } else {
  642. var deltaMode = event.originalEvent.deltaMode;
  643. var delta = event.originalEvent.deltaY;
  644. // FireFox case: deltaMode is always 1 for zoom in/out. Formula is the same as VIDA demo page
  645. if (deltaMode === 1) {
  646. delta = delta * 100 / 3;
  647. }
  648. // Follow VIDA demo to use deltaY. Formula used to calculate the scale is 1 - .002 * i, where i = event.deltaY
  649. return 1 - ZOOM_VELOCITY * delta;
  650. }
  651. };
  652. /**
  653. * Checks item source's to see if it contains forecast info
  654. * @param {Object} itemSource - target item.source
  655. * @return true if the target item is forecast data, otherwise false
  656. */
  657. VIPREventTarget.prototype._isForecastData = function _isForecastData(itemSource) {
  658. return itemSource && itemSource.deco && itemSource.deco.forecast;
  659. };
  660. return VIPREventTarget;
  661. }(EventTarget);
  662. return VIPREventTarget;
  663. });
  664. //# sourceMappingURL=VIPREventTarget.js.map