123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291 |
- 'use strict';
- var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
- function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
- 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; }
- 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; }
- /**
- *+------------------------------------------------------------------------+
- *| Licensed Materials - Property of IBM
- *| IBM Cognos Products: Dashboard
- *| (C) Copyright IBM Corp. 2018, 2019
- *|
- *| US Government Users Restricted Rights - Use, duplication or disclosure
- *| restricted by GSA ADP Schedule Contract with IBM Corp.
- *+------------------------------------------------------------------------+
- */
- define(['underscore', './AbstractTupleLocator'], function (_, AbstractTupleLocator) {
- var BinarySearchTupleLocator = function (_AbstractTupleLocator) {
- _inherits(BinarySearchTupleLocator, _AbstractTupleLocator);
- /**
- * A tuple locator which deals with tuples which the VIDA getItemsInPolygon
- * API returns.
- */
- function BinarySearchTupleLocator(_ref) {
- var viprWidget = _ref.viprWidget;
- _classCallCheck(this, BinarySearchTupleLocator);
- var _this = _possibleConstructorReturn(this, _AbstractTupleLocator.call(this));
- _this.viprWidget = viprWidget;
- return _this;
- }
- /* For JSDocs, see parent class */
- BinarySearchTupleLocator.prototype.findTupleVisualInfo = function findTupleVisualInfo(filter, _ref2) {
- var _this2 = this;
- var includeInfo = _ref2.includeInfo,
- includePoints = _ref2.includePoints;
- var viprItems = _.flatten(
- //Get all items in an area
- this._getVisAreas().map(function (_ref3) {
- var x = _ref3.x,
- y = _ref3.y,
- w = _ref3.w,
- h = _ref3.h;
- return _this2._getVIDAItemsInRectangle({ x0: x, y0: y, x1: x + w, y1: y + h })
- //Filter items to ones which satisfy specified filter
- .filter(function (item) {
- return _this2._itemSatisfiesFilter({ item: item, filter: filter });
- });
- }));
- return viprItems.map(function (item) {
- var result = {};
- if (includeInfo) {
- result.info = _this2._getValueInfoFromItem(item);
- }
- if (includePoints) {
- result.point = _this2._getPoint(item);
- }
- return result;
- });
- };
- /*
- * Finds the areas (e.g. "visualization", "legend") and their extents which
- * VIPR partitions the entire visualization into.
- *
- * Motivation: It is important to know their extents, as if a
- * getItemsInPolygon query draws a polygon with points straddling multiple
- * areas, VIPR will return no items.
- *
- * @return {object[]} area information will include 'area' (name), 'x', 'y',
- * 'w' and 'h'
- */
- BinarySearchTupleLocator.prototype._getVisAreas = function _getVisAreas() {
- var _this3 = this;
- var bounds = this.viprWidget.domNode.getBoundingClientRect();
- var areaToExtents = {};
- //Assume all areas we care about begin in one of the four corners of the
- //visualization.
- var findAreasFromCorner = function findAreasFromCorner(bx, by) {
- var w0 = bx ? bounds.width - 1 : 0,
- h0 = by ? bounds.height - 1 : 0;
- var getArea = function getArea(w, h) {
- return _this3.viprWidget.getVisCoordinate(bounds.x + w, bounds.y + h).area;
- };
- //What area is in this corner?
- var area = getArea(w0, h0);
- //'none' is not a useful area; and if we've already found the extents of
- //this area, no need to scan again
- if (area === 'none' || areaToExtents[area]) {
- return;
- }
- var dx = bx ? -1 : 1,
- dy = by ? -1 : 1;
- var wt = void 0,
- ht = void 0;
- //Scan x axis to see how wide this area is
- for (wt = w0; 0 <= wt && wt < bounds.width; wt += dx) {
- if (getArea(wt, h0) !== area) {
- break;
- }
- }
- wt -= dx;
- //Scan y axis to see how tall this area is
- for (ht = h0; 0 <= ht && ht < bounds.height; ht += dy) {
- if (getArea(w0, ht) !== area) {
- break;
- }
- }
- ht -= dy;
- //Assume areas are rectangular
- areaToExtents[area] = {
- x: Math.min(w0, wt),
- y: Math.min(h0, ht),
- w: Math.abs(w0 - wt),
- h: Math.abs(h0 - ht)
- };
- };
- //Search for areas in all four corners
- findAreasFromCorner(false, false); //top-left
- findAreasFromCorner(true, false); //top-right
- findAreasFromCorner(false, true); //bottom-left
- findAreasFromCorner(true, true); //bottom-right
- //In general, the only area we use is 'visualization'. If it's not found
- //we won't be able to proceed
- if (!areaToExtents.visualization) {
- throw new Error('Cannot find "visualization" area of widget');
- }
- return Object.keys(areaToExtents).map(function (area) {
- return { extents: areaToExtents[area], area: area };
- }).map(function (_ref4) {
- var extents = _ref4.extents,
- area = _ref4.area;
- return _extends({}, extents, { area: area });
- });
- };
- /*
- * Simplifies the VIPR getItemsInPolygon API to a rectangle - and takes care
- * of the mapping to VIPR coordinate space via getVisCoordinate.
- * @param {object} coords
- * @param {number} coords.x0 - top-left corner x coordinate
- * @param {number} coords.y0 - top-left corner y coordinate
- * @param {number} coords.x1 - bottom-right corner x coordinate
- * @param {number} coords.y1 - bottom-right corner y coordinate
- */
- BinarySearchTupleLocator.prototype._getVIDAItemsInRectangle = function _getVIDAItemsInRectangle(_ref5) {
- var _this4 = this;
- var x0 = _ref5.x0,
- y0 = _ref5.y0,
- x1 = _ref5.x1,
- y1 = _ref5.y1;
- var origin = this.viprWidget.domNode.getBoundingClientRect();
- //Make a 'rectangle' polygon:
- // - top-left corner
- // - top-right corner
- // - bottom-right corner
- // - bottom-left corner
- var points = [[x0, y0], [x1, y0], [x1, y1], [x0, y1]].map(function (_ref6) {
- var x = _ref6[0],
- y = _ref6[1];
- return [x + origin.x, y + origin.y];
- }).map(function (_ref7) {
- var x = _ref7[0],
- y = _ref7[1];
- return _this4.viprWidget.getVisCoordinate(x, y);
- });
- return this.viprWidget.getItemsInPolygon(points);
- };
- /*
- * Finds a single clickable point which will click an item
- * @param {object} item
- */
- BinarySearchTupleLocator.prototype._getPoint = function _getPoint(item) {
- var _this5 = this;
- //Find which area this item is contained in and extract its extents
- var extent = this._getVisAreas().find(function (_ref8) {
- var x = _ref8.x,
- y = _ref8.y,
- w = _ref8.w,
- h = _ref8.h;
- return _this5._isItemContainedIn(item, { x0: x, y0: y, x1: x + w, y1: y + h });
- });
- if (!extent) {
- throw new Error('Item not found at any position within visualization');
- }
- var x0 = extent.x,
- y0 = extent.y,
- x1 = x0 + extent.w,
- y1 = y0 + extent.h;
- //Find the boundary between where this item does and does not exist in the x axis
- var x = this._binarySearch(x1, x0, function (x) {
- return _this5._isItemContainedIn(item, { x0: x0, y0: y0, x1: x, y1: y1 });
- });
- //Find the boundary between where this item does and does not exist along the strip of x axis found above
- var y = this._binarySearch(y1, y0, function (y) {
- return _this5._isItemContainedIn(item, { x0: x - 1, y0: y0, x1: x, y1: y });
- });
- return {
- selectedNode: this.viprWidget.domNode,
- xOffset: x,
- yOffset: y
- };
- };
- /*
- * Perform a binary search for the boundary between a condition succeeding and failing
- * @param {number} maxPass - the maximum value where the condition is known to pass
- * @param {number} maxFail - the maximum value where the condition is known to fail
- * @param {function} test - condition
- */
- BinarySearchTupleLocator.prototype._binarySearch = function _binarySearch(maxPass, maxFail, test) {
- while (Math.abs(maxPass - maxFail) > 1) {
- var candidate = Math.round((maxPass + maxFail) / 2);
- if (test(candidate)) {
- maxPass = candidate;
- } else {
- maxFail = candidate;
- }
- }
- return maxPass;
- };
- /*
- * Determines whether the item exists inside a particular rectangle in the visualization
- * @param {object} item
- * @param {object} extents - rectangle
- */
- BinarySearchTupleLocator.prototype._isItemContainedIn = function _isItemContainedIn(item, _ref9) {
- var x0 = _ref9.x0,
- y0 = _ref9.y0,
- x1 = _ref9.x1,
- y1 = _ref9.y1;
- return this._getVIDAItemsInRectangle({ x0: x0, y0: y0, x1: x1, y1: y1 }).some(function (foundItem) {
- return item.key === foundItem.key;
- });
- };
- return BinarySearchTupleLocator;
- }(AbstractTupleLocator);
- return BinarySearchTupleLocator;
- });
- //# sourceMappingURL=BinarySearchTupleLocator.js.map
|