JQGrid.js 48 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367
  1. 'use strict';
  2. 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; };
  3. var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
  4. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  5. /**
  6. * Licensed Materials - Property of IBM
  7. * IBM Cognos Products: Dashboard
  8. * (C) Copyright IBM Corp. 2014, 2020
  9. * US Government Users Restricted Rights - Use, duplication or disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
  10. *
  11. * JQuery datatables grid control (JQGrid).
  12. * @module com/ibm/ui/render/grid/control/JQGrid
  13. */
  14. define(['underscore', 'jquery', '../../../../util/DashboardFormatter', '../../../../widgets/livewidget/nls/StringResources', '../GridDataProcessor', '../GridDropTarget', '../GridDnDManager', '../../../../dataSources/metadata/MetadataColumn', '../RankProcessor', '../GridDataProvider', '../GridContentRenderer', 'react-dom', 'react', 'ca-ui-toolkit'], function (_, $, Formatter, StringResources, GridDataProcessor, GridDropTarget, GridDnDManager, MetadataColumn, RankProcessor, DataProvider, GridContentRenderer, ReactDOM, React, Toolkit) {
  15. var SLOT_ID = 'grid_cols';
  16. var SUMMARY_COLS_THRESHOLD = 12;
  17. var ROW_HEADER_INDEX = 0;
  18. var LABEL = 'label';
  19. var VALUE = 'value';
  20. var DEFAULT_ROW_HEIGHT = 32;
  21. var PROP_ID_SUPPRESSION = 'suppression';
  22. var SUMMARY_ID = StringResources.get('summaryCaption');
  23. return function () {
  24. function JQGrid() {
  25. _classCallCheck(this, JQGrid);
  26. this.init(arguments.length <= 0 ? undefined : arguments[0]);
  27. }
  28. JQGrid.prototype.init = function init() {
  29. var _this = this;
  30. var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  31. this.domNode = options.domNode;
  32. this.gridView = options.gridView;
  33. this.colorsService = options.dashboardApi.getFeature('Colors');
  34. this.tabNavigation = options.tabNavigation;
  35. this.conditionalFormatting = options.conditionalFormatting;
  36. this.cellRenderer = options.cellRenderer;
  37. this._dataRows = null; //Data used by the grid in row form.
  38. this._focusNode = null;
  39. this._heatByIndex = -1;
  40. this._heatIndice = [];
  41. this._colorAllColumns = false;
  42. this._bGroupingEnabled = true;
  43. this._filterableSlots = [];
  44. this._selectedCellCache = {};
  45. this._slotFormatCache = {};
  46. this._rankDataItems = [];
  47. this._columnDataItems = [];
  48. this._visModel = options.visModel;
  49. this._hideSummaries = false;
  50. this._hasTopBottomLimit = null;
  51. this._columnsInfo = {
  52. groupedIndices: [],
  53. factIndices: []
  54. };
  55. var content = this.gridView && this.gridView.content;
  56. this.summaryFeature = options.summaryFeature;
  57. this.visualization = content.getFeature('Visualization');
  58. this._gridDnDManager = new GridDnDManager({
  59. grid: this,
  60. dashboardApi: options.dashboardApi,
  61. content: content,
  62. gridEdgeMappedToId: { row: SLOT_ID }
  63. });
  64. this._setSummaryColor = function (gridCellProps) {
  65. var summaryColor = _this.conditionalFormatting && _this.conditionalFormatting.getSummaryFillColor();
  66. if (summaryColor) {
  67. _.extend(gridCellProps.style, { 'background-color': summaryColor });
  68. }
  69. };
  70. };
  71. /**
  72. * Resets the table - should be called before the first call to setData.
  73. * @param {object} visModel
  74. */
  75. JQGrid.prototype.reset = function reset(visModel) {
  76. this._visModel = visModel;
  77. this._heatIndice = [];
  78. this._heatByIndex = -1;
  79. this._colorAllColumns = false;
  80. this._columnSlot = this.visualization.getSlots().getSlot('grid_cols');
  81. this._heatSlot = this.visualization.getSlots().getSlot('heat');
  82. this._slots = [this._columnSlot, this._heatSlot];
  83. this._rankDataItems = [];
  84. this._columnDataItems = [];
  85. this._dataRows = [];
  86. this._hasTopBottomLimit = null;
  87. this._columnsInfo = {
  88. groupedIndices: [],
  89. factIndices: []
  90. };
  91. };
  92. // These configurations need the rank to be processed before being set
  93. JQGrid.prototype._whenRankProcessed = function _whenRankProcessed() {
  94. this._columnDataItems = this._rankDataItems.concat(this._columnSlot && this._columnSlot.getDataItemList() || []);
  95. this._filterHeatBySlot(this.visualization.getSlots().getSlotList());
  96. this._setColumnsInfo();
  97. this._doGrouping = this._columnsInfo && !(this._columnsInfo.disableGrouping || this._hasTopBottomLimit);
  98. this._setDoSummaryInfo();
  99. };
  100. JQGrid.prototype._setDoSummaryInfo = function _setDoSummaryInfo() {
  101. this._hideSummaries = this._visModel.getPropertyValue('hideSummaries');
  102. if (this._hideSummaries === undefined && (this._columnDataItems ? this._columnDataItems.length : 0) > SUMMARY_COLS_THRESHOLD) {
  103. // only override the default of hideSummaries on the first time Through
  104. // sanity check for defect 247618 to mitigate risk of crash on initial rendering of very large tables
  105. // user can change at own risk after first render
  106. this._hideSummaries = true;
  107. this.gridView.ownerWidget.updateVisProperties({
  108. id: 'hideSummaries',
  109. value: true
  110. }, {
  111. silent: true
  112. });
  113. }
  114. var hasFactInColumn = this._columnsInfo.factIndices.length;
  115. var hasGroup = this._columnsInfo.groupedIndices.length;
  116. this._doSummary = hasFactInColumn && hasGroup && !this._hideSummaries && this._doGrouping;
  117. };
  118. JQGrid.prototype._setColumnsInfo = function _setColumnsInfo() {
  119. if (this._columnDataItems && this._columnDataItems.length) {
  120. var numberOfColumns = this._columnDataItems.length;
  121. var groupedIndices = [];
  122. var factIndices = [];
  123. this._columnsInfo = {};
  124. this._setLeftMostFactSlotIndex();
  125. // const bPreviousColumnHasUserSort = true;
  126. // const bCheckForDisableGrouping = true;
  127. this._columnsInfo.disableGrouping = false;
  128. for (var columnIndex = 0; columnIndex < numberOfColumns; columnIndex++) {
  129. var dataItem = this._columnDataItems[columnIndex];
  130. //TODO: Add Top-N support here
  131. // const mapping = slot.getMapping();
  132. // if (!this._hasTopBottomLimit) {
  133. // const limit = mapping.getLimit ? mapping.getLimit() : undefined;
  134. // this._hasTopBottomLimit = (limit !== undefined);
  135. // }
  136. //TODO: Rewrite this logic to use new model
  137. if (this._columnCanBeGrouped(columnIndex)) {
  138. groupedIndices.push(columnIndex);
  139. }
  140. if (this._isFactOrAggregationSet(dataItem) || this.isRank(columnIndex)) {
  141. factIndices.push(columnIndex);
  142. }
  143. }
  144. this._columnsInfo.factIndices = factIndices;
  145. this._columnsInfo.groupedIndices = groupedIndices;
  146. }
  147. };
  148. JQGrid.prototype._setLeftMostFactSlotIndex = function _setLeftMostFactSlotIndex() {
  149. delete this._columnsInfo.leftMostFactSlotIndex;
  150. for (var i = 0; i < this._columnDataItems.length; i++) {
  151. if (this._isFactOrAggregationSet(this._columnDataItems[i]) || this.isRank(i)) {
  152. this._columnsInfo.leftMostFactSlotIndex = i;
  153. break;
  154. }
  155. }
  156. };
  157. /**
  158. * A slot can be grouped (i.e. only one value displayed if there is muliple )
  159. * IF it is an attribute OR it has an attribute concept (like cAge, cWeek, cDate) attatched to it OR slot definition indicates group = true.
  160. * Otherwise, it should not be grouped (as in the case of measures like Quantity or Units Sold). See RTC 73968 for details.
  161. * @param colIndex - index of the column in question
  162. * @returns true if the slot should be grouped...false if each value should be rendered even if it is the same as the previous row.
  163. *
  164. */
  165. JQGrid.prototype._columnCanBeGrouped = function _columnCanBeGrouped(colIndex) {
  166. var leftMostCol = this._columnsInfo.leftMostFactSlotIndex;
  167. if (!_.isUndefined(leftMostCol) && colIndex >= leftMostCol) {
  168. return false;
  169. }
  170. return this._columnDataItems[colIndex].getType() === 'attribute';
  171. //TODO: Put in equivalent for this condition:
  172. //|| (slot.getDefinition() && slot.getDefinition().group)
  173. };
  174. JQGrid.prototype._filterHeatBySlot = function _filterHeatBySlot(dataSlots) {
  175. var _this2 = this;
  176. if (!this._hasDataMappings()) {
  177. return;
  178. }
  179. var index = this.getRankDataItemCount();
  180. var heatDataItemList = this._heatSlot.getDataItemList();
  181. var heatByColumnId = this._heatSlot && heatDataItemList.length > 0 ? heatDataItemList[0].getColumnId() : null;
  182. //return an array containing all of the non-heat slots and
  183. //locate what column index in the data that the heat slot will be located
  184. var newSlots = _.filter(dataSlots, function (slot) {
  185. var dataItemList = slot.getDataItemList();
  186. if (dataItemList.length == 0) {
  187. return false;
  188. }
  189. if (slot.getId() === 'heat') {
  190. _this2._heatByIndex = index++;
  191. // ignore heat slot
  192. return false;
  193. } else {
  194. index += dataItemList.length;
  195. return true;
  196. }
  197. });
  198. // Collect the slots indice that matches the heatby column id
  199. if (heatByColumnId) {
  200. index = this.getRankDataItemCount();
  201. _.each(newSlots, function (slot) {
  202. var dataItemList = slot.getDataItemList();
  203. //slots now contain more than 1 data item so have to iterate over the data items inside
  204. if (dataItemList.length > 0) {
  205. var itemIds = _.map(dataItemList, function (dataItem) {
  206. return dataItem.getColumnId();
  207. });
  208. _.each(itemIds, function (dataItemId) {
  209. if (dataItemId === heatByColumnId) {
  210. _this2._heatIndice.push(index);
  211. }
  212. index++;
  213. });
  214. }
  215. });
  216. // format the entire row. -1 in the array indicates that heat slot
  217. // is populated but the column is not displayed in the grid
  218. if (this._heatIndice.length === 0) {
  219. this._colorAllColumns = true;
  220. }
  221. }
  222. return newSlots;
  223. };
  224. JQGrid.prototype.setData = function setData(queryResult) {
  225. this._queryResult = queryResult;
  226. this._processRank();
  227. };
  228. JQGrid.prototype.hasData = function hasData() {
  229. return !!this._queryResult;
  230. };
  231. JQGrid.prototype.setStyles = function setStyles(styleObj) {
  232. if (styleObj) {
  233. this.headerStyles = styleObj.headerStyles;
  234. this.cellStyles = styleObj.cellStyles;
  235. }
  236. };
  237. JQGrid.prototype.resetOnRender = function resetOnRender() {
  238. if (this._groupedConditionalColor) {
  239. delete this._groupedConditionalColor;
  240. }
  241. this._setDoSummaryInfo();
  242. };
  243. // Modifies original data, should not be called more than once per data set
  244. JQGrid.prototype._processRank = function _processRank() {
  245. var rankProcessor = new RankProcessor(this._queryResult, this.findSlotDetailsByRealColumnIndex.bind(this));
  246. this._rankDataItems = rankProcessor.processData();
  247. this._whenRankProcessed();
  248. };
  249. JQGrid.prototype._generateDataRows = function _generateDataRows() {
  250. var _this3 = this;
  251. // rank processor is only called once upon setData for new query result
  252. // client side format change will no longer trigger a new query, but the model change will trigger a reset on visModel
  253. // need to make sure that the columnInfo is set in this scenario
  254. if (this._columnDataItems.length === 0) {
  255. this._whenRankProcessed();
  256. }
  257. this._resetOnGetDataRows();
  258. var dataProcessor = new GridDataProcessor({
  259. 'queryResult': this._queryResult,
  260. 'numberOfColumns': this._columnDataItems ? this._columnDataItems.length : 0,
  261. 'exceedsColumnThreshold': (this._columnDataItems ? this._columnDataItems.length : 0) > SUMMARY_COLS_THRESHOLD,
  262. 'columnSlot': this._columnSlot,
  263. 'rankDataItems': this._rankDataItems,
  264. 'columnDataItems': this._columnDataItems,
  265. 'lastGroupedColumnIndex': this._columnsInfo ? this._columnsInfo.leftMostFactSlotIndex : 0,
  266. 'visModel': this._visModel,
  267. 'factColumnIndices': this._columnsInfo ? this._columnsInfo.factIndices : 0,
  268. 'doSummary': this._doSummary,
  269. 'onCellDataChange': this._onCellDataChange.bind(this),
  270. 'getRankFormat': this._getRankFormat,
  271. 'getRealColumnIndex': this.getRealColumnIndex.bind(this),
  272. 'summaryFeature': this.summaryFeature
  273. });
  274. return dataProcessor.getData().then(function (dataRows) {
  275. _this3._dataRows = dataRows;
  276. if (_this3._columnDataItems.length > 0) {
  277. _this3._headers = _this3._columnDataItems.map(function (dataItem, index) {
  278. var label = dataItem.getLabel();
  279. if (_this3.isRank(index)) {
  280. label = StringResources.get('topBottomRankLabel', {
  281. label: label
  282. });
  283. }
  284. return label;
  285. });
  286. }
  287. _this3._dataRows.unshift(_this3._headers);
  288. _this3._WhenDataRowsAreReady();
  289. //TODO: clean-up is to remove the unnecessary creation of summary value promises;
  290. // this can definitely be done when we have only one request but also without this: as discussed, we could wait for the summary promises to be resolved only
  291. dataProcessor.whenAllSummaryValuesAreReady().then(_this3.onResize.bind(_this3));
  292. });
  293. };
  294. JQGrid.prototype.onResize = function onResize() {
  295. this.maxColHeight = this._getMaxColHeight();
  296. this.gridRef && this.gridRef.recomputeGridSize();
  297. };
  298. JQGrid.prototype.render = function render(resizing, renderingNewData) {
  299. var _this4 = this;
  300. if (this.gridRef && resizing && !renderingNewData) {
  301. //if only do resizing
  302. this.onResize();
  303. this.onSyncScrollBar();
  304. return Promise.resolve(true);
  305. } else {
  306. // dataChange will change the rowNum and colNum of the data, need to re-render the grid
  307. //reset summary indicator flag
  308. if (!this._errorWarningAdded) {
  309. this.gridView && this.gridView.clearInfoIndicator('error_summary_cell');
  310. } else {
  311. this._errorWarningAdded = false;
  312. }
  313. this.resetOnRender();
  314. return this._generateDataRows().then(this._renderReactGrid.bind(this)).then(function () {
  315. return !!_this4.gridRef;
  316. });
  317. }
  318. };
  319. JQGrid.prototype.onSyncScrollBar = function onSyncScrollBar() {
  320. // when parent dom is moved or updated the scrollLeft and scrollTop value reset to 0 for the bottom-right-grid
  321. // this is a bug in React MultiGrid Level
  322. // the fix here is to sync the scrollBar among the three grid before onResize is triggered
  323. var $domNode = $(this.domNode);
  324. var rightBottomGrid = $domNode.find('.ba-common-grid__bottom-right-grid');
  325. var rightTopGrid = $domNode.find('.ba-common-grid__top-right-grid');
  326. var visibleChildrenCells = $(rightBottomGrid).find('.bottom-right-grid-cell');
  327. var firstVisibleChild = visibleChildrenCells && visibleChildrenCells[0];
  328. $(rightBottomGrid).animate({
  329. scrollLeft: $(rightTopGrid).scrollLeft(),
  330. scrollTop: firstVisibleChild && firstVisibleChild.offsetTop || 1
  331. }, 0);
  332. };
  333. /**
  334. * Set selections context which contains row edge selection, column edge selection
  335. * and datapoint selection
  336. **/
  337. JQGrid.prototype.setSelections = function setSelections(selections) {
  338. var _this5 = this;
  339. this._selections = selections;
  340. this._selectionValues = [];
  341. this._selectedCellCache = {};
  342. this._selections.forEach(function (selection) {
  343. var _tempSelection = [];
  344. Object.values(selection).forEach(function (s) {
  345. _tempSelection.push(s.u);
  346. });
  347. _this5._selectionValues.push(_tempSelection);
  348. });
  349. };
  350. JQGrid.prototype._getDataCellValue = function _getDataCellValue(dataCellValue, valueType) {
  351. if (dataCellValue === null || dataCellValue === undefined) {
  352. return;
  353. }
  354. if (valueType === 'useValue') {
  355. dataCellValue = this._getValue(dataCellValue, VALUE);
  356. } else if (valueType === 'type') {
  357. dataCellValue = dataCellValue.type;
  358. } else if (valueType === 'isSummary') {
  359. dataCellValue = dataCellValue.isSummary;
  360. } else if (valueType === 'summaryOf') {
  361. dataCellValue = dataCellValue.summaryOf;
  362. } else if (valueType === 'tuple') {
  363. dataCellValue = dataCellValue.key;
  364. } else if (valueType === 'rank') {
  365. dataCellValue = dataCellValue.value && (dataCellValue.value.deco && dataCellValue.value.deco.rank || dataCellValue.value.value) || dataCellValue.value;
  366. } else {
  367. if (dataCellValue.isSummary && this._getValue(dataCellValue, VALUE) === dataCellValue.summaryOf) {
  368. dataCellValue = SUMMARY_ID;
  369. } else {
  370. dataCellValue = this._getValue(dataCellValue, LABEL);
  371. }
  372. }
  373. return dataCellValue;
  374. };
  375. /**
  376. * Removes cell-is-focused classname if there's no selections
  377. *
  378. * @param aClassString
  379. * @return {*}
  380. * @private
  381. */
  382. JQGrid.prototype._removeFocusedClassName = function _removeFocusedClassName(aClassString) {
  383. var SELECTED = 'cell-is-focused';
  384. if (Array.isArray(this._selections) && this._selections.length === 0) {
  385. if (aClassString.indexOf(SELECTED) !== -1) {
  386. return aClassString.replace(SELECTED, '').trim();
  387. }
  388. }
  389. return aClassString;
  390. };
  391. JQGrid.prototype._getValueForRowAtIndex = function _getValueForRowAtIndex(row, colIndex) {
  392. var cell = row[colIndex];
  393. if (cell.value && cell.value.value) {
  394. return cell.value.value;
  395. } else if (cell[0]) {
  396. return cell[0].value;
  397. } else {
  398. return null;
  399. }
  400. };
  401. JQGrid.prototype._calculateSelectionForFact = function _calculateSelectionForFact(rowIndex) {
  402. var row = this._dataRows[rowIndex + 1];
  403. var isSelected = false;
  404. var attributeValues = [];
  405. for (var i = 0; i < row.length; i++) {
  406. if (!(this._columnsInfo.factIndices.indexOf(i) !== -1)) {
  407. var cellValue = this._getValueForRowAtIndex(row, i);
  408. attributeValues.push(cellValue);
  409. }
  410. }
  411. this._selectionValues.forEach(function (selection) {
  412. if (_.difference(selection, attributeValues).length === 0) {
  413. isSelected = true;
  414. }
  415. });
  416. return isSelected;
  417. };
  418. JQGrid.prototype._calculateSelectionForAttribute = function _calculateSelectionForAttribute(rowIndex, colIndex) {
  419. var row = this._dataRows[rowIndex + 1];
  420. for (var i = 0; i < colIndex + 1; i++) {
  421. if (!(this._columnsInfo.factIndices.indexOf(i) !== -1)) {
  422. var cellValue = this._getValueForRowAtIndex(row, i);
  423. if (!(_.flatten(this._selectionValues).indexOf(cellValue) !== -1)) {
  424. return false;
  425. }
  426. }
  427. }
  428. return true;
  429. };
  430. /**
  431. * Determine if a cell should be selected based on the selection info
  432. *
  433. * @param {object} dataValue
  434. * @param {number} colIndex
  435. * @return {boolean}
  436. * @private
  437. */
  438. JQGrid.prototype._isCellSelected = function _isCellSelected(rowIndex, colIndex) {
  439. var cacheKey = rowIndex + '-' + colIndex;
  440. if (this._selectedCellCache[cacheKey] !== undefined) {
  441. return this._selectedCellCache[cacheKey];
  442. }
  443. var isSelected = false;
  444. if (this._selectionValues.length > 0) {
  445. if (this._columnsInfo.factIndices.indexOf(colIndex) !== -1) {
  446. isSelected = this._calculateSelectionForFact(rowIndex);
  447. } else {
  448. isSelected = this._calculateSelectionForAttribute(rowIndex, colIndex);
  449. }
  450. }
  451. this._selectedCellCache[cacheKey] = isSelected;
  452. return isSelected;
  453. };
  454. JQGrid.prototype._getCellPropertyColors = function _getCellPropertyColors() {
  455. try {
  456. // if user customized a background color for current widget
  457. var fillColor = this.gridView && this.gridView.content && this.gridView.content.getPropertyValue('fillColor');
  458. var cellFillColor = fillColor && this.colorsService.getHexColorFromDashboardColorSet(fillColor);
  459. // TODO: have our own theme mapping for new grid
  460. var foregroundColorProperties = fillColor && this.colorsService.getForegroundColorPropertiesForUIElement(fillColor, 'tabs');
  461. var cellTextColor = foregroundColorProperties && foregroundColorProperties.length && foregroundColorProperties[0].value;
  462. return {
  463. cellFillColor: cellFillColor,
  464. cellTextColor: cellTextColor
  465. };
  466. } catch (err) {
  467. return {};
  468. }
  469. };
  470. JQGrid.prototype._prepFormatCache = function _prepFormatCache(numColumns) {
  471. this._slotFormatCache = {};
  472. for (var i = 0; i < numColumns; i++) {
  473. var _findSlotDetails = this.findSlotDetails(i),
  474. slot = _findSlotDetails.slot,
  475. mapIndex = _findSlotDetails.mapIndex;
  476. this._slotFormatCache[i] = slot.getDataItemList()[mapIndex].getFormat(mapIndex); // this call is expensive!
  477. }
  478. };
  479. JQGrid.prototype._renderReactGrid = function _renderReactGrid() {
  480. var _this6 = this;
  481. var _dataProvider = new DataProvider(this._dataRows);
  482. var fixedRows = 1;
  483. var numColumns = _dataProvider.getNumColumns();
  484. var numRows = _dataProvider.getNumRows() - fixedRows;
  485. var dataRows = _dataProvider.getNumRows() - (_dataProvider.getNumRows() - this._queryResult.getRowCount());
  486. this._prepFormatCache(numColumns);
  487. // in story, the first-time rendering from dashboard, the offsetHeight of the node is 0, need to check this
  488. this.maxColHeight = this._getMaxColHeight();
  489. var TABINDEX = 0;
  490. var summaryRowIdxs = [];
  491. var isSuppressed = this._isSuppressionOn();
  492. var _getCellPropertyColor = this._getCellPropertyColors(),
  493. cellFillColor = _getCellPropertyColor.cellFillColor,
  494. cellTextColor = _getCellPropertyColor.cellTextColor;
  495. var _shapeCols = [];
  496. // find heat dataItem position so it is associated with its fact column
  497. var heatColumnPosition = this._determineHeatColumnPosition();
  498. var dataCellRenderer = function dataCellRenderer(rowIndex, colIndex, gridCellProps) {
  499. try {
  500. var dataValue = _dataProvider.getValue(rowIndex + fixedRows, colIndex);
  501. var isSummary = _this6._getDataCellValue(dataValue, 'isSummary');
  502. var isRank = _this6.isRank(colIndex);
  503. var isMeasure = colIndex < _this6._columnDataItems.length && _this6._isFactOrAggregationSet(_this6._columnDataItems[colIndex]);
  504. //Summary values are already formatted so only format non-summary values
  505. var rawDataCellValue = _this6._getDataCellValue(dataValue);
  506. var dataCellValue = isSummary ? rawDataCellValue : isRank ? _this6._getDataCellValue(dataValue, 'rank') : _this6._formatValue(rawDataCellValue, colIndex, isSummary, isSuppressed);
  507. //populate the attributes we needed
  508. gridCellProps['row'] = rowIndex + fixedRows;
  509. gridCellProps['col'] = colIndex;
  510. gridCellProps['aria-label'] = dataCellValue;
  511. gridCellProps['tabindex'] = TABINDEX;
  512. gridCellProps.className = _this6._removeFocusedClassName(gridCellProps.className);
  513. var classList = [gridCellProps.className];
  514. classList.push('grid-data-cell', 'dashboard-grid-cell');
  515. gridCellProps.style = _.extend(gridCellProps.style, {});
  516. // background color from Property
  517. if (cellFillColor && !isSummary) {
  518. gridCellProps.style = _.extend(gridCellProps.style, {
  519. backgroundColor: cellFillColor,
  520. color: cellTextColor
  521. });
  522. }
  523. //Text toolbar style applied
  524. var values = Object.assign({}, _this6.cellStyles);
  525. Object.keys(values).forEach(function (key) {
  526. return values[key] === '' && delete values[key];
  527. });
  528. gridCellProps.style = Object.assign(gridCellProps.style, values);
  529. //summary row background
  530. var summaryCnt = 0;
  531. if (isSummary) {
  532. classList.push('summary');
  533. var found = summaryRowIdxs.find(function (ele) {
  534. return rowIndex === ele;
  535. });
  536. if (!found) {
  537. summaryRowIdxs.push(rowIndex);
  538. }
  539. }
  540. // determine summary row cnt for conditional formatting
  541. summaryRowIdxs.forEach(function (idx) {
  542. if (rowIndex > idx) {
  543. summaryCnt++;
  544. }
  545. });
  546. //Conditional Formatting
  547. if (!isSummary && rowIndex < dataRows + summaryCnt && !dataValue.hasLeafNode) {
  548. var conditionalColor = _this6._getConditionalColor(rowIndex - summaryCnt, colIndex, dataValue, heatColumnPosition);
  549. if (conditionalColor) {
  550. if (!_this6.conditionalFormatting) {
  551. _.extend(gridCellProps.style, conditionalColor.getStyle());
  552. } else {
  553. _.extend(gridCellProps.style, conditionalColor);
  554. }
  555. }
  556. }
  557. // colspan/rowspan
  558. var rowSpan = 0;
  559. var colSpan = 0;
  560. var isTransparent = false;
  561. if (_this6.isGroupedColumn(colIndex) && !isSummary) {
  562. if (cellFillColor === 'transparent' && _this6._getDataCellValue(_dataProvider.getValue(rowIndex + fixedRows - 1, colIndex)) === dataCellValue) {
  563. isTransparent = true;
  564. }
  565. var rowSpanIndex = rowIndex + fixedRows + 1;
  566. //iterate over the rows in this row until we find one that is different
  567. while (rowSpanIndex <= numRows + fixedRows - 1 && _this6._getDataCellValue(_dataProvider.getValue(rowSpanIndex, colIndex)) === rawDataCellValue && _this6._getDataCellValue(_dataProvider.getValue(rowSpanIndex, 0)) === _this6._getDataCellValue(_dataProvider.getValue(rowIndex + fixedRows, 0))) {
  568. rowSpanIndex++;
  569. }
  570. rowSpan = rowSpanIndex - (rowIndex + fixedRows);
  571. var _height = parseInt(gridCellProps.style.height, 10) * rowSpan;
  572. gridCellProps.style.height = Math.min(_height, _this6.maxColHeight) + 'px';
  573. }
  574. if (isSummary && !isMeasure) {
  575. var colSpanIndex = colIndex + 1;
  576. while (colSpanIndex <= numColumns + 1 && _this6._getDataCellValue(_dataProvider.getValue(rowIndex + fixedRows, colSpanIndex)) === dataCellValue) {
  577. colSpanIndex++;
  578. }
  579. colSpan = colSpanIndex - colIndex;
  580. gridCellProps.style.width = parseInt(gridCellProps.style.width, 10) * colSpan + 'px';
  581. }
  582. if (rowSpan || colSpan) {
  583. gridCellProps.style.zIndex = colSpan > rowSpan ? colSpan : rowSpan;
  584. }
  585. //render selection highlight and implied_selection for fact column
  586. if (!isSummary && _this6._isCellSelected(rowIndex, colIndex)) {
  587. classList.push('dashboard-grid-cell-selected');
  588. }
  589. if (isMeasure) {
  590. classList.push('measure');
  591. }
  592. gridCellProps.className = classList.join(' ');
  593. var value = isTransparent ? '' : dataCellValue;
  594. var contentSpec = {
  595. displayValue: value
  596. };
  597. var isShapeCol = _shapeCols.indexOf(colIndex) !== -1;
  598. if (isShapeCol || gridCellProps.style.shapeId) {
  599. if (!isShapeCol) {
  600. _shapeCols.push(colIndex);
  601. }
  602. contentSpec.shapeId = gridCellProps.style.shapeId;
  603. }
  604. var children = void 0;
  605. if (_this6.cellRenderer && _this6.cellRenderer.canRender()) {
  606. // This code is currently not used. It is only here to provide an extension point for rendering cell content
  607. var _value = void 0;
  608. // The summary values are inconsistent with the rest values
  609. // A better way is to fix the root cause and make things consistent..
  610. // but for now, we adjust things here to make the value format consistent before we call the extension
  611. if (dataValue.isSummary) {
  612. _value = {};
  613. if (_typeof(dataValue.value) === 'object') {
  614. _value.label = dataValue.value.label;
  615. _value.value = dataValue.value.value;
  616. } else {
  617. _value.label = dataValue.value;
  618. _value.value = dataValue.rawValue || dataValue.value;
  619. }
  620. } else {
  621. _value = dataValue.value;
  622. }
  623. var _isRank = _this6.isRank(colIndex);
  624. var dataItemIndex = _this6.isRank(colIndex) ? _this6.getRefIndex(colIndex) + _this6.getRankDataItemCount() : colIndex;
  625. var state = {
  626. dataItem: _this6._columnDataItems[dataItemIndex],
  627. dataValue: _value,
  628. rowIndex: rowIndex,
  629. colIndex: colIndex
  630. };
  631. if (_isRank) {
  632. state.isRank = true;
  633. }
  634. if (dataValue.isSummary) {
  635. state.isSummary = true;
  636. }
  637. children = _this6.cellRenderer.getComponentList(state);
  638. } else {
  639. children = [];
  640. }
  641. if (children.length === 0) {
  642. children.push(React.createElement(GridContentRenderer, _extends({}, contentSpec, { key: colIndex })));
  643. }
  644. if (isSummary) {
  645. children.push(React.createElement('div', { className: 'grid-summary-decorator' }, ''));
  646. _this6._setSummaryColor(gridCellProps);
  647. } else {
  648. children.push(React.createElement('div', { class: 'grid-drop-zone left' }, ''));
  649. children.push(React.createElement('div', { class: 'grid-drop-zone replace' }, ''));
  650. children.push(React.createElement('div', { class: 'grid-drop-zone right' }, ''));
  651. }
  652. return React.createElement(GridDropTarget, _extends({ dndManager: _this6._gridDnDManager, cellType: 'column' }, gridCellProps), children);
  653. } catch (err) {
  654. // livewidget_cleanup
  655. // An error might occure because this function seems to access destroyed objects.
  656. // This happens when the grid is being re-rendered, and for some reason this function
  657. // gets called before the re-render and since it references destroyed obbect (i.e. deleted dataitems)
  658. // we will get an exception
  659. // No need to do anything and the re-render will occur and things should be fine
  660. // But we need to understand more why this is happening.
  661. }
  662. };
  663. var fixedRowCellRenderer = function fixedRowCellRenderer(rowIndex, colIndex, gridCellProps) {
  664. var dataValue = _dataProvider.getValue(rowIndex, colIndex);
  665. var isSummary = _this6._getDataCellValue(dataValue, 'isSummary');
  666. var dataCellValue = _this6._getDataCellValue(dataValue);
  667. //populate the attributes we needed
  668. gridCellProps['row'] = rowIndex;
  669. gridCellProps['col'] = colIndex;
  670. gridCellProps['scope'] = 'col';
  671. gridCellProps['aria-label'] = dataCellValue;
  672. gridCellProps['tabindex'] = TABINDEX;
  673. gridCellProps.className = _this6._removeFocusedClassName(gridCellProps.className);
  674. var classList = [gridCellProps.className];
  675. classList.push('grid-fixed-row-cell', 'dashboard-grid-cell');
  676. gridCellProps.style = _.extend(gridCellProps.style, {});
  677. //Text toolbar style applied
  678. gridCellProps.style = _.extend(gridCellProps.style, _this6.headerStyles);
  679. gridCellProps.className = classList.join(' ');
  680. var textCellChildren = [dataCellValue];
  681. //Add sorting indicator if any exists
  682. var sortType = _this6._getSortType(colIndex);
  683. if (sortType) {
  684. var orderClass = sortType === 'asc' ? 'wfg_sorted_asc' : 'wfg_sorted_desc';
  685. var sortingIndicator = React.createElement('span', {
  686. className: orderClass
  687. }, '');
  688. textCellChildren.push(sortingIndicator);
  689. }
  690. var children = [React.createElement('div', { className: 'dashboard-text-cell' }, textCellChildren)];
  691. if (isSummary) {
  692. children.push(React.createElement('div', { className: 'grid-summary-decorator' }, ''));
  693. } else {
  694. children.push(React.createElement('div', { class: 'grid-drop-zone left' }, ''));
  695. children.push(React.createElement('div', { class: 'grid-drop-zone replace' }, ''));
  696. children.push(React.createElement('div', { class: 'grid-drop-zone right' }, ''));
  697. }
  698. return React.createElement(GridDropTarget, _extends({ dndManager: _this6._gridDnDManager, cellType: 'column' }, gridCellProps), children);
  699. };
  700. var rowHeight = function rowHeight() {
  701. return DEFAULT_ROW_HEIGHT;
  702. };
  703. var columnWidth = function columnWidth() {
  704. var minCellWidth = 100;
  705. var viewPortWidth = _this6.domNode.clientWidth;
  706. if (_this6.domNode.clientHeight / DEFAULT_ROW_HEIGHT < numRows) {
  707. // when vertical scrollbar is visible, it takes up the width space of current view port, which is 17px among all types of browsers and increase 1px for windows machine
  708. var scrollBarWidth = 18;
  709. viewPortWidth = viewPortWidth - scrollBarWidth;
  710. } else {
  711. // IE has around 1px differences than the other browsers
  712. var calWidthDiff = 1;
  713. viewPortWidth = viewPortWidth - calWidthDiff;
  714. }
  715. var adjustedCellWidth = parseInt(viewPortWidth / numColumns);
  716. return Math.max(adjustedCellWidth, minCellWidth);
  717. };
  718. var overscanRowCount = 2;
  719. if ((this._columnDataItems ? this._columnDataItems.length : 0) > SUMMARY_COLS_THRESHOLD) {
  720. // We know we won't have groups in this scenario, so its safe to overscan more rows.
  721. // RTC #290279 - Crosstab and Grid will sometimes show blank cells when row span is active
  722. overscanRowCount = 20;
  723. }
  724. var style = {};
  725. var props = {
  726. rowHeight: rowHeight,
  727. columnWidth: columnWidth,
  728. numColumns: numColumns,
  729. numRows: numRows,
  730. fixedRows: fixedRows,
  731. overscanRowCount: overscanRowCount,
  732. dataCellRenderer: dataCellRenderer,
  733. fixedRowCellRenderer: fixedRowCellRenderer,
  734. style: style,
  735. ref: function ref(node) {
  736. _this6.gridRef = node;
  737. },
  738. maxColumnWidth: Infinity
  739. };
  740. var contextualGrid = React.createElement(Toolkit.Grid, props);
  741. this.$el = $(this.domNode).addClass('dashboard-common-grid').addClass('table-grid');
  742. ReactDOM.render(contextualGrid, this.domNode);
  743. this.gridRef && this.gridRef.recomputeGridSize();
  744. };
  745. JQGrid.prototype._getMaxColHeight = function _getMaxColHeight() {
  746. return this.domNode.offsetHeight || Infinity;
  747. };
  748. /**
  749. * Callback for handling when data dynamically changes from the pivot
  750. * @param {number} row - row index of the pivot data
  751. * @param {number} column - column index of the pivot data
  752. * @param {string} value - formatted value of the changed data
  753. */
  754. JQGrid.prototype._onCellDataChange = function _onCellDataChange(row, column, value, rawValue) {
  755. if (!this._dataRowsIsReady) {
  756. this._delayedCellUpdate.push({ row: row, column: column, value: value, rawValue: rawValue });
  757. }
  758. // When the value is error, add warning icon only once
  759. if (value && value.error) {
  760. if (!this._errorWarningAdded) {
  761. this.gridView.onSummaryDataCellError();
  762. this._errorWarningAdded = true;
  763. }
  764. value = StringResources.get('value_is_not_available');
  765. }
  766. if (this._dataRows && row < this._dataRows.length && column < this._dataRows[row].length && this._dataRows[row][column].value !== value) {
  767. this._dataRows[row][column].value = value;
  768. this._dataRows[row][column].rawValue = rawValue;
  769. }
  770. };
  771. /**
  772. * For scenario that summaryValue is ready before dataRows are ready, we need to delay the cell update once the dataRows are resolved
  773. */
  774. JQGrid.prototype._WhenDataRowsAreReady = function _WhenDataRowsAreReady() {
  775. var _this7 = this;
  776. this._dataRowsIsReady = true;
  777. this._delayedCellUpdate.forEach(function (cell) {
  778. return _this7._onCellDataChange(cell.row, cell.column, cell.value, cell.rawValue);
  779. });
  780. };
  781. /**
  782. * Reset the dataRowsIsReady flag and delayedCellUpdates when dataRows are regenerated
  783. */
  784. JQGrid.prototype._resetOnGetDataRows = function _resetOnGetDataRows() {
  785. this._dataRowsIsReady = false;
  786. this._delayedCellUpdate = [];
  787. };
  788. /**
  789. *
  790. * @param {*} value could be an object, an array or a string
  791. * @param {String} type either displayValue or useValue
  792. */
  793. JQGrid.prototype._getValue = function _getValue(value, type) {
  794. if (value === null || value === undefined) {
  795. return;
  796. }
  797. // Since the query result value is also in the form of {value: 'aaa', label: 'AAA'}
  798. // Need to differentiate query result value vs. internal generated value from EdgeIterator
  799. if (value.value !== undefined && value.descendant_or_self !== undefined) {
  800. value = value.value;
  801. }
  802. if (value !== null && value !== undefined) {
  803. if (value[type] !== undefined) {
  804. // Get the either display or use value
  805. return value[type];
  806. }
  807. // When value has a nested value object
  808. if (value.value && _typeof(value.value) === 'object') {
  809. return this._getValue(value.value, type);
  810. }
  811. // If label is missing, return use value
  812. if (type === LABEL && value.value !== undefined) {
  813. return value.value;
  814. }
  815. }
  816. // When value is an array
  817. if (_.isArray(value) && value[0]) {
  818. return this._getValue(value[0], type);
  819. }
  820. return value;
  821. };
  822. JQGrid.prototype.setValue = function setValue($td, value, rowIndex, colIndex) {
  823. var cellValue = this._getValue(value, LABEL);
  824. var bIsSummary = (typeof value === 'undefined' ? 'undefined' : _typeof(value)) === 'object' && 'isSummary' in value ? value.isSummary : this._dataRows[rowIndex][colIndex].isSummary;
  825. //Fixup the label for summary row so it gets rendered properly
  826. if (bIsSummary) {
  827. if (this._getValue(value, VALUE) === value.summaryOf) {
  828. cellValue = SUMMARY_ID;
  829. }
  830. } else if (rowIndex !== ROW_HEADER_INDEX) {
  831. //Summary values are already formatted so only format non-summary values
  832. cellValue = this._formatValue(cellValue, colIndex, bIsSummary);
  833. }
  834. $td.attr('aria-label', cellValue);
  835. $td.text(cellValue);
  836. };
  837. JQGrid.prototype._getSortType = function _getSortType(colIndex) {
  838. // Find the correct slot and index of data item in it
  839. var _findSlotDetails2 = this.findSlotDetails(colIndex),
  840. slot = _findSlotDetails2.slot,
  841. mapIndex = _findSlotDetails2.mapIndex;
  842. // If not sorted by rank hide sort icon for rank column, if sorted by rank hide sort icon for the non-rank column
  843. var dataItem = slot.getDataItemList()[mapIndex];
  844. var dataItemSort = dataItem && dataItem.getSort();
  845. if (dataItemSort) {
  846. if (this.isRank(colIndex) && !dataItemSort.rankSort || !this.isRank(colIndex) && dataItemSort.rankSort) {
  847. return null;
  848. }
  849. }
  850. return dataItemSort && !dataItem.hasDefaultSort() && dataItemSort.type;
  851. };
  852. // Rank columns should always be formatted as number
  853. JQGrid.prototype._getRankFormat = function _getRankFormat() {
  854. return {
  855. formatSpec: {
  856. 'selectedFormat': 'none',
  857. 'maximumFractionDigits': 0,
  858. 'formatLength': 'short',
  859. 'type': 'number',
  860. 'locale': this._columnSlot.locale
  861. },
  862. validFormatSpec: {
  863. 'selectedFormat': 'none',
  864. 'maximumFractionDigits': 0,
  865. 'formatLength': 'short',
  866. 'type': 'number',
  867. 'locale': this._columnSlot.locale
  868. }
  869. };
  870. };
  871. JQGrid.prototype._formatValue = function _formatValue(cellValue, colIndex, bIsSummary, isSuppressed) {
  872. var format = void 0;
  873. if (this.isRank(colIndex)) {
  874. format = this._rankFormat;
  875. } else {
  876. format = this._slotFormatCache[colIndex];
  877. }
  878. if (!bIsSummary) {
  879. return isSuppressed ? Formatter.format(cellValue, format) : Formatter.formatNull(cellValue, format);
  880. } else {
  881. // only format the summary row for number
  882. var dataItem = this._columnDataItems[colIndex];
  883. if (dataItem && this._isFactOrAggregationSet(dataItem)) {
  884. return isSuppressed ? Formatter.format(cellValue, format) : Formatter.formatNull(cellValue, format);
  885. }
  886. return cellValue;
  887. }
  888. };
  889. JQGrid.prototype._isSuppressionOn = function _isSuppressionOn() {
  890. var content = this.gridView && this.gridView.content;
  891. var suppressionValue = content && content.getPropertyValue(PROP_ID_SUPPRESSION);
  892. if (suppressionValue && suppressionValue === 'none') {
  893. return false;
  894. }
  895. return true;
  896. };
  897. /**
  898. * Callback for handling when data dynamically changes from the pivot
  899. *
  900. * @param {number} iRow - row index of the pivot data
  901. * @param {number} iCol - column index of the pivot data
  902. * @param {number} dataValue - value of the data
  903. * @param {Array} heatColumnPosition - an array of the column position against the heat slot
  904. */
  905. JQGrid.prototype._getConditionalColor = function _getConditionalColor(iRow, iCol, dataValue, heatColumnPosition) {
  906. /*
  907. * A grid can be colored if there is a heat slot populated. _heatIndice contains the index of the heat column that is displayed in
  908. * the grid, which causes only that column to be colored. If the first value is -1, that means the heat slot is populated but the column
  909. * is not displayed in the grid; thus, all columns are colored.
  910. */
  911. // If this is a rank column, look at the referenced table column
  912. var colIndex = this.isRank(iCol) ? this.getRefIndex(iCol) + this.getRankDataItemCount() : iCol;
  913. if (!this.conditionalFormatting) {
  914. var conditionalPalette = this._visModel.getConditions() ? this._visModel.getConditions().palette : null;
  915. if (conditionalPalette && (this._heatIndice.indexOf(colIndex) > -1 || colIndex == this._heatByIndex || this._colorAllColumns)) {
  916. //return conditionalPalette.getColorByValue(this._heatByDataRows[iRow]);
  917. var oValue = this._queryResult.getValue(iRow, this._heatByIndex);
  918. var conditionalColor = conditionalPalette.getColorByValue(this._getValue(oValue, VALUE));
  919. if (conditionalColor && this.cellStyles && this.cellStyles.color) {
  920. delete conditionalColor.color;
  921. }
  922. return conditionalColor;
  923. }
  924. } else {
  925. if (this._heatByIndex !== -1 && heatColumnPosition.length) {
  926. var heatOffset = heatColumnPosition.indexOf(colIndex);
  927. if (heatOffset !== -1) {
  928. var condValue = this._queryResult.getValue(iRow, this._heatByIndex + heatOffset);
  929. var dataItem = this._columnDataItems[colIndex];
  930. var baseValue = dataValue.value.value ? dataValue.value.value : dataValue.value;
  931. return this.conditionalFormatting.getFormatting(baseValue, condValue.value, dataItem.getColumnId());
  932. }
  933. }
  934. }
  935. return null;
  936. };
  937. /**
  938. * Gets a list of the nodes that have been selected
  939. * @return {Array.node} - an array of nodes
  940. */
  941. JQGrid.prototype.getSelectedColumnHeaderNodes = function getSelectedColumnHeaderNodes() {
  942. return $(this.domNode).find('.header-cell.implied_selection');
  943. };
  944. /**
  945. * highlight the column header
  946. */
  947. JQGrid.prototype.hilightColumn = function hilightColumn(selectedNode, bSingleSelect, bDeselect, bRightClick) {
  948. var $node = $(selectedNode);
  949. if (bDeselect && bRightClick) {
  950. return;
  951. }
  952. if (bSingleSelect) {
  953. this.clearColumnHighlight();
  954. }
  955. if (bDeselect) {
  956. $node.removeClass('implied_selection');
  957. } else {
  958. $node.addClass('implied_selection');
  959. }
  960. };
  961. JQGrid.prototype.clearColumnHighlight = function clearColumnHighlight() {
  962. $(this.domNode).find('.header-cell.implied_selection').removeClass('implied_selection');
  963. };
  964. /**
  965. * @returns true if the current node includes the 'selected' or 'selected_secondary' or 'implied_selection' class.
  966. */
  967. JQGrid.prototype.isCellSelected = function isCellSelected(node) {
  968. var $node = $(node);
  969. return $node.hasClass('dashboard-grid-cell-selected') || $node.hasClass('implied_selection');
  970. };
  971. JQGrid.prototype.isGroupedColumn = function isGroupedColumn(columnNodeOrColumnIndex) {
  972. var columnIndex = columnNodeOrColumnIndex;
  973. if ((typeof columnNodeOrColumnIndex === 'undefined' ? 'undefined' : _typeof(columnNodeOrColumnIndex)) === 'object') {
  974. columnIndex = this.getColumnIndex(columnNodeOrColumnIndex);
  975. }
  976. return this._columnsInfo.groupedIndices && this._columnsInfo.groupedIndices.indexOf(parseInt(columnIndex)) !== -1;
  977. };
  978. JQGrid.prototype._isFactColumn = function _isFactColumn(columnIndex) {
  979. return this._columnsInfo.factIndices.indexOf(parseInt(columnIndex)) !== -1;
  980. };
  981. JQGrid.prototype.getRowIndexFromSelectedNode = function getRowIndexFromSelectedNode(selectedNode) {
  982. return parseInt($(selectedNode).attr('row'), 10);
  983. };
  984. JQGrid.prototype.getColumnIndex = function getColumnIndex(cellNode) {
  985. return parseInt($(cellNode).attr('col'), 10);
  986. };
  987. JQGrid.prototype._hasDataMappings = function _hasDataMappings() {
  988. return this.visualization.getSlots().getMappedSlotList().length > 0;
  989. };
  990. JQGrid.prototype.getColumnCount = function getColumnCount() {
  991. return this._columnDataItems.length;
  992. };
  993. /**
  994. * Find the slot, index of slot in JQGrid._slots and item's mapIndex in that slot
  995. * @param colIndex Column index in the table
  996. */
  997. JQGrid.prototype.findSlotDetails = function findSlotDetails(colIndex) {
  998. var realColumnIndex = this.getRealColumnIndex(colIndex);
  999. return this.findSlotDetailsByRealColumnIndex(realColumnIndex);
  1000. };
  1001. /**
  1002. * The rank value can depend on a value which exists in either column slot or heat slot
  1003. * When we need to fetch information from the slot, we should detect which slot we should use.
  1004. * Function returns the correct slot, its index in JQGrid._slots and data item's mapIndex in the slot.
  1005. *
  1006. * @param columnIndex Data item index in the original data
  1007. */
  1008. JQGrid.prototype.findSlotDetailsByRealColumnIndex = function findSlotDetailsByRealColumnIndex(columnIndex) {
  1009. var prevItemCount = 0;
  1010. var slot = null;
  1011. var mapIndex = null; // index of item in slot
  1012. var slotIndex = 0; // index of the slot
  1013. for (var i = 0; i < this._slots.length; i++) {
  1014. slot = this._slots[i];
  1015. var slotItemCount = slot.getDataItemList().length;
  1016. if (columnIndex < slotItemCount + prevItemCount) {
  1017. mapIndex = columnIndex - prevItemCount;
  1018. slotIndex = i;
  1019. break;
  1020. } else {
  1021. prevItemCount += slotItemCount;
  1022. }
  1023. }
  1024. return { slot: slot, slotIndex: slotIndex, mapIndex: mapIndex };
  1025. };
  1026. /**
  1027. * Returns the real index of data item in the original query result data
  1028. * given the column's index on the table.
  1029. *
  1030. * @param {*} colIndex column index on the table
  1031. */
  1032. JQGrid.prototype.getRealColumnIndex = function getRealColumnIndex(colIndex) {
  1033. return this.isRank(colIndex) ? this.getRefIndex(colIndex) : colIndex - this.getRankDataItemCount();
  1034. };
  1035. JQGrid.prototype.getRankDataItemCount = function getRankDataItemCount() {
  1036. return this._rankDataItems && this._rankDataItems.length || 0;
  1037. };
  1038. /**
  1039. * Determines whether the given column mapping is a rank column
  1040. * @param columIndex: index of the column in the table
  1041. */
  1042. JQGrid.prototype.isRank = function isRank(columIndex) {
  1043. return !!(this._columnDataItems[columIndex] && this._columnDataItems[columIndex].isRank) || false;
  1044. };
  1045. /**
  1046. * Returns the 'original' index of a data column that is being referenced by a rank column.
  1047. * This is the index of the referenced column BEFORE the Rank Processor modified the data.
  1048. * In order to get to the visible (rendered) column index, we should add the _rankDataItems.length to this.
  1049. *
  1050. * @param colIndex index of the rank
  1051. */
  1052. JQGrid.prototype.getRefIndex = function getRefIndex(colIndex) {
  1053. return this._columnDataItems[colIndex].getRefColumnIndex && this._columnDataItems[colIndex].getRefColumnIndex();
  1054. };
  1055. /**
  1056. * Set focusNode and clear existing user selection (focus)
  1057. */
  1058. JQGrid.prototype.updateFocusNode = function updateFocusNode(focusNode) {
  1059. var bDeselect = $(focusNode).hasClass('focused') || this.isCellSelected(focusNode);
  1060. if (this._focusNode) {
  1061. this._focusNode.removeClass('focused');
  1062. }
  1063. if (bDeselect) {
  1064. return;
  1065. }
  1066. this._focusNode = $(focusNode);
  1067. this._focusNode.addClass('focused');
  1068. };
  1069. JQGrid.prototype.remove = function remove() {
  1070. this.gridView = null;
  1071. this.tabNavigation = null;
  1072. this._rankDataItems = null;
  1073. this._dataRows = null;
  1074. this._headers = null;
  1075. this._dataRowsIsReady = null;
  1076. this._delayedCellUpdate = null;
  1077. this.removeGridView();
  1078. this.domNode = null;
  1079. };
  1080. JQGrid.prototype.removeGridView = function removeGridView() {
  1081. if (this.gridRef && this.domNode) {
  1082. ReactDOM.unmountComponentAtNode(this.domNode);
  1083. this.gridRef = null;
  1084. }
  1085. };
  1086. JQGrid.prototype.onEnterContainer = function onEnterContainer() {
  1087. var firstCellNode = $(this.domNode).find('.top-right-grid-cell[row="0"][col="0"]');
  1088. if (firstCellNode.length) {
  1089. firstCellNode.focus();
  1090. }
  1091. };
  1092. JQGrid.prototype.handleSelectColumnHeader = function handleSelectColumnHeader(selectedNode, bSingleSelect, bRightClick) {
  1093. //Existing column header will still be highlighted if the ctrl key is held
  1094. var bDeselect = this.isCellSelected(selectedNode);
  1095. this.hilightColumn(selectedNode, bSingleSelect, bDeselect, bRightClick);
  1096. };
  1097. JQGrid.prototype._isFactOrAggregationSet = function _isFactOrAggregationSet(dataItem) {
  1098. if (!dataItem) {
  1099. return false;
  1100. }
  1101. if (dataItem.getType() === 'fact') {
  1102. return true;
  1103. } else {
  1104. if (dataItem.getAggregation() !== MetadataColumn.AGGREGATION_TYPE_MAP.none) {
  1105. return true;
  1106. }
  1107. return false;
  1108. }
  1109. };
  1110. JQGrid.prototype.showDropZone = function showDropZone(selector) {
  1111. this.hideDropZones();
  1112. this.$el.find(selector).css({ 'display': 'block' });
  1113. };
  1114. JQGrid.prototype.hideDropZones = function hideDropZones() {
  1115. this.$el.find('.grid-drop-zone').css({ 'display': 'none' });
  1116. };
  1117. JQGrid.prototype.showReplaceDropZone = function showReplaceDropZone(idx) {
  1118. var type = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'col';
  1119. this.showDropZone('[' + type + '=' + idx + '] > .grid-drop-zone');
  1120. };
  1121. JQGrid.prototype.showLeftDropZone = function showLeftDropZone(col) {
  1122. this.showDropZone('[col=' + col + '] > .grid-drop-zone.left');
  1123. };
  1124. JQGrid.prototype.showRightDropZone = function showRightDropZone(col) {
  1125. this.showDropZone('[col=' + col + '] > .grid-drop-zone.right');
  1126. };
  1127. /**
  1128. * Determine the column position relative to the heat slot
  1129. */
  1130. JQGrid.prototype._determineHeatColumnPosition = function _determineHeatColumnPosition() {
  1131. var _this8 = this;
  1132. var heatPos = [];
  1133. var condFormats = this.conditionalFormatting && this.conditionalFormatting.getConditionalFormatting();
  1134. if (condFormats) {
  1135. this._heatSlot.getDataItemList().forEach(function (dataItem) {
  1136. var condFormat = condFormats.conditionalFormats.find(function (cf) {
  1137. return cf.heatId === dataItem.getId();
  1138. });
  1139. if (condFormat) {
  1140. heatPos.push(_this8._columnsInfo.factIndices.find(function (factIndex) {
  1141. return !_this8.isRank(factIndex) && condFormat.dataItemId === _this8._columnDataItems[factIndex].getColumnId();
  1142. }));
  1143. }
  1144. });
  1145. }
  1146. return heatPos;
  1147. };
  1148. return JQGrid;
  1149. }();
  1150. });
  1151. //# sourceMappingURL=JQGrid.js.map