@refinitiv-ui/efx-grid 6.0.108 → 6.0.110

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -44,7 +44,8 @@ declare namespace ColumnDefinition {
44
44
  leftPinned?: boolean|null,
45
45
  rightPinned?: boolean|null,
46
46
  info?: any,
47
- focusable?: boolean|null
47
+ focusable?: boolean|null,
48
+ backgroundColor?: string|null
48
49
  };
49
50
 
50
51
  }
@@ -161,6 +162,10 @@ declare class ColumnDefinition {
161
162
 
162
163
  public isFocusable(): boolean;
163
164
 
165
+ public getBackgroundColor(): string;
166
+
167
+ public setBackgroundColor(color: string): void;
168
+
164
169
  }
165
170
 
166
171
  declare const COL_DEF: string;
@@ -51,6 +51,7 @@ import Engine from "../../tr-grid-util/es6/formula/Engine.js";
51
51
  * @property {boolean=} rightPinned=false If enabled, the column will not be part of the scrollable area and is pinned to the right side
52
52
  * @property {Object=} info=null For storing any additional information to the column
53
53
  * @property {boolean=} focusable=false If enabled, the column will be used to find focusable element when pressing tab key
54
+ * @property {string=} backgroundColor CSS color value
54
55
  */
55
56
 
56
57
  /** mapping of field type to javascript type
@@ -1169,6 +1170,24 @@ ColumnDefinition.prototype._setCoreColumnDef = function(obj) {
1169
1170
  ColumnDefinition.prototype.isFocusable = function() {
1170
1171
  return this._focusable;
1171
1172
  };
1173
+ /** @public
1174
+ * @return {string}
1175
+ */
1176
+ ColumnDefinition.prototype.getBackgroundColor = function() {
1177
+ let core = this._eventArg["core"];
1178
+ let grid = this._eventArg["grid"];
1179
+ let colIndex = grid.getColumnIndex(this);
1180
+ return core.getColumnBackgroundColor(colIndex);
1181
+ };
1182
+ /** @public
1183
+ * @param {string} color
1184
+ */
1185
+ ColumnDefinition.prototype.setBackgroundColor = function(color) {
1186
+ let core = this._eventArg["core"];
1187
+ let grid = this._eventArg["grid"];
1188
+ let colIndex = grid.getColumnIndex(this);
1189
+ core.setColumnBackgroundColor(colIndex, color);
1190
+ };
1172
1191
 
1173
1192
  export {ColumnDefinition, COL_DEF};
1174
1193
  export default ColumnDefinition;
@@ -174,6 +174,10 @@ declare class Grid extends EventDispatcher {
174
174
 
175
175
  public setColumnName(colIndex: number, str: string): void;
176
176
 
177
+ public getColumnBackgroundColor(colRef: Grid.ColumnReference|null): string;
178
+
179
+ public setColumnBackgroundColor(colRef: Grid.ColumnReference|null, color: string): void;
180
+
177
181
  public setColumnRenderer(colRef: Grid.ColumnReference|null, func?: ((...params: any[]) => any)|null): void;
178
182
 
179
183
  public activateColumnRenderer(colRef: Grid.ColumnReference|null, id?: string|null, func?: ((...params: any[]) => any)|null): void;
@@ -321,7 +321,7 @@ let Grid = function(placeholder, config) {
321
321
  t._snapshotFillerDataChanged = t._snapshotFillerDataChanged.bind(t);
322
322
  t._onPollingInterval = t._onPollingInterval.bind(t);
323
323
 
324
- t._onKeyDown = t._onKeyDown.bind(t);
324
+ t._onTabNavigation = t._onTabNavigation.bind(t);
325
325
  t._requestScroll = t._requestScroll.bind(t);
326
326
  t._onVScroll = t._onVScroll.bind(t);
327
327
  t._selfScrollToRow = t._selfScrollToRow.bind(t);
@@ -404,10 +404,9 @@ let Grid = function(placeholder, config) {
404
404
  t._grid.listen("postSectionDataBinding", t._onPostSectionDataBinding);
405
405
  t._grid.listen("firstRendered", t._dispatch.bind(t, "firstRendered"));
406
406
  t._grid.listen("afterContentBinding", t._dispatch.bind(t, "afterContentBinding"));
407
- t._grid.listen("keydown", t._onKeyDown);
407
+ t._grid.listen("tabNavigation", t._onTabNavigation);
408
408
 
409
409
  t._grid.getVScrollbar().listen("scroll", t._onVScroll);
410
- t._hiddenInput = t._grid.getHiddenInput();
411
410
 
412
411
  t._grid.enableRowHighlighting(true);
413
412
 
@@ -634,8 +633,10 @@ Grid.prototype.dispose = function() {
634
633
  this._subs = null;
635
634
  }
636
635
 
637
- if(this._focusingArgs && this._focusingArgs.id) {
638
- clearTimeout(this._focusingArgs.id);
636
+ if(this._focusingArgs) {
637
+ if(this._focusingArgs.id) {
638
+ clearTimeout(this._focusingArgs.id);
639
+ }
639
640
  this._focusingArgs = null;
640
641
  }
641
642
  };
@@ -2169,6 +2170,27 @@ Grid.prototype.setColumnName = function(colIndex, str) {
2169
2170
  };
2170
2171
  /** @public
2171
2172
  * @param {Grid~ColumnReference} colRef
2173
+ * @return {string}
2174
+ */
2175
+ Grid.prototype.getColumnBackgroundColor = function(colRef) {
2176
+ let colDef = this.getColumnDefinition(colRef);
2177
+ if(colDef) {
2178
+ return colDef.getBackgroundColor();
2179
+ }
2180
+ return "";
2181
+ };
2182
+ /** @public
2183
+ * @param {Grid~ColumnReference} colRef
2184
+ * @param {string} color
2185
+ */
2186
+ Grid.prototype.setColumnBackgroundColor = function(colRef, color) {
2187
+ let colDef = this.getColumnDefinition(colRef);
2188
+ if(colDef) {
2189
+ colDef.setBackgroundColor(color);
2190
+ }
2191
+ };
2192
+ /** @public
2193
+ * @param {Grid~ColumnReference} colRef
2172
2194
  * @param {Function=} func
2173
2195
  */
2174
2196
  Grid.prototype.setColumnRenderer = function(colRef, func) {
@@ -4123,16 +4145,11 @@ Grid.prototype.getVScrollView = function () {
4123
4145
  * @param {Element} el
4124
4146
  * @return {boolean}
4125
4147
  */
4126
- function isValidInput(el) {
4127
- return el && el.tagName !== "SPAN" && !el.disabled;
4128
- }
4129
- /** @private
4130
- * @param {Element} el
4131
- * @param {Element} hiddenInput
4132
- * @return {boolean}
4133
- */
4134
- function isValidTarget(el, hiddenInput) {
4135
- return !el.classList.contains("valigner") && el !== hiddenInput;
4148
+ function isFocusableContent(el) {
4149
+ if(el) {
4150
+ return (el.tagName !== "SPAN" && !el.disabled);
4151
+ }
4152
+ return false;
4136
4153
  }
4137
4154
  /** @private
4138
4155
  * @param {Object} cell
@@ -4141,7 +4158,7 @@ function isValidTarget(el, hiddenInput) {
4141
4158
  function focusCell(cell) {
4142
4159
  if(cell) {
4143
4160
  let cellContent = cell.getContent();
4144
- if(cellContent && isValidInput(cellContent)) {
4161
+ if(cellContent && isFocusableContent(cellContent)) {
4145
4162
  cellContent.focus();
4146
4163
  return true;
4147
4164
  }
@@ -4152,18 +4169,15 @@ function focusCell(cell) {
4152
4169
  */
4153
4170
  Grid.prototype._onVScroll = function() {
4154
4171
  let args = this._focusingArgs;
4155
- if(!args) { return; }
4156
-
4157
- this._focusingArgs = null;
4158
- let event = args.event;
4159
- let cell = args.section.getCell(args.colIndex, args.rowIndex);
4160
- if(focusCell(cell)) {
4161
- event.preventDefault();
4162
- } else {
4163
- if(event.shiftKey) {
4164
- this._findPrevFocusableCell(event, args.colIndex, args.rowIndex, args.focusableColIndices);
4165
- } else {
4166
- this._findNextFocusableCell(event, args.colIndex, args.rowIndex, args.focusableColIndices);
4172
+ if(args) {
4173
+ this._focusingArgs = null;
4174
+ let cell = this._grid.getCell("content", args.colIndex, args.rowIndex);
4175
+ if(!focusCell(cell)) {
4176
+ if(args.shiftKey) {
4177
+ this._focusPrevCellContent(args);
4178
+ } else {
4179
+ this._focusNextCellContent(args);
4180
+ }
4167
4181
  }
4168
4182
  }
4169
4183
  };
@@ -4171,89 +4185,108 @@ Grid.prototype._onVScroll = function() {
4171
4185
  */
4172
4186
  Grid.prototype._selfScrollToRow = function() {
4173
4187
  let args = this._focusingArgs;
4174
- if(!args) { return; }
4175
- args.id = 0;
4176
- this.scrollToRow(args.rowIndex);
4188
+ if(args) {
4189
+ args.id = 0;
4190
+ this.scrollToRow(args.rowIndex);
4191
+ }
4177
4192
  };
4178
4193
  /** @private
4179
- * @param {Object} e
4194
+ * @param {Object} args
4180
4195
  * @param {number} colIndex
4181
4196
  * @param {number} rowIndex
4182
- * @param {Array} focusableColIndices
4183
- * @param {Object} section
4184
4197
  */
4185
- Grid.prototype._requestScroll = function(e, colIndex, rowIndex, focusableColIndices, section) {
4186
- let args = this._focusingArgs;
4187
- if(args) { return; }
4188
- if(this._scrolledRow === rowIndex) { return; } // Avoid infinite loop
4189
-
4190
- this._scrolledRow = rowIndex;
4191
- args = this._focusingArgs = {
4192
- event: e,
4193
- colIndex: colIndex,
4194
- rowIndex: rowIndex,
4195
- focusableColIndices: focusableColIndices,
4196
- section: section
4197
- };
4198
+ Grid.prototype._requestScroll = function(args, colIndex, rowIndex) {
4199
+ if(this._focusingArgs || this._scrolledRow === args.rowIndex) {
4200
+ return; // Avoid infinite loop
4201
+ }
4198
4202
 
4203
+ this._scrolledRow = args.rowIndex;
4204
+ this._focusingArgs = args;
4205
+ args.colIndex = colIndex;
4206
+ args.rowIndex = rowIndex;
4207
+ args.event = null; // The event is invalid after the scroll
4199
4208
  args.id = setTimeout(this._selfScrollToRow); // Avoid event loop protection
4200
4209
  };
4201
4210
  /** @private
4202
- * @param {Object} e
4203
- * @param {number} colIndex
4204
- * @param {number} rowIndex
4205
- * @param {Array} focusableColIndices
4206
- * @param {Element=} content
4211
+ * @param {Object} args
4207
4212
  */
4208
- Grid.prototype._findNextFocusableCell = function(e, colIndex, rowIndex, focusableColIndices, content) {
4209
- let startIdx = focusableColIndices.indexOf(colIndex);
4213
+ Grid.prototype._focusNextCellContent = function(args) {
4214
+ let colIndex = args.colIndex;
4215
+ let rowIndex = args.rowIndex;
4216
+ if(rowIndex < 0 || rowIndex == null) {
4217
+ return;
4218
+ }
4210
4219
 
4211
- // Calculate starting row and column index
4212
- if(!isValidTarget(e.target, this._hiddenInput) || startIdx < 0) {
4213
- rowIndex = 0;
4214
- startIdx = 0;
4215
- } else if(isValidInput(content) && startIdx >= 0) {
4220
+ let focusableColIndices = args.focusableColIndices;
4221
+ let len = focusableColIndices.length;
4222
+ let startIdx = 0;
4223
+ let i;
4224
+ if(colIndex >= 0) {
4225
+ for(i = 1; i < len; i++) {
4226
+ if(colIndex < focusableColIndices[i]) {
4227
+ break;
4228
+ }
4229
+ startIdx = i;
4230
+ }
4231
+ }
4232
+ // If the current focus is on a valid content, starts on the next cell
4233
+ if(args.event && args.validContent) {
4216
4234
  startIdx++;
4217
4235
  }
4236
+
4218
4237
  let grid = this._grid;
4219
4238
  let section = grid.getSection("content");
4220
4239
  let viewInfo = grid.getVerticalViewInfo();
4221
4240
  let bottomRowIndex = viewInfo.bottomRowIndex;
4222
4241
  let rowCount = this.getRowCount();
4223
4242
  for(let r = rowIndex; r < rowCount; r++) {
4224
- for(let i = startIdx; i < focusableColIndices.length; i++) {
4243
+ for(i = startIdx; i < len; i++) {
4225
4244
  let c = focusableColIndices[i];
4226
4245
  if(r > bottomRowIndex) {
4227
- this._requestScroll(e, c, r, focusableColIndices, section);
4246
+ this._requestScroll(args, c, r);
4228
4247
  return;
4229
4248
  } else {
4230
4249
  let cell = section.getCell(c, r);
4231
4250
  if(focusCell(cell)) {
4232
- e.preventDefault();
4251
+ if(args.event) {
4252
+ args.event.preventDefault();
4253
+ }
4233
4254
  return;
4234
4255
  }
4235
4256
  }
4236
4257
  }
4237
4258
  startIdx = 0;
4238
4259
  }
4260
+
4261
+ if(args.validContent) { // The current focus on the last focusable content
4262
+ this._grid.getHiddenInput().focus();
4263
+ }
4239
4264
  };
4240
4265
  /** @private
4241
- * @param {Object} e
4242
- * @param {number} colIndex
4243
- * @param {number} rowIndex
4244
- * @param {Array} focusableColIndices
4245
- * @param {Element=} content
4266
+ * @param {Object} args
4246
4267
  */
4247
- Grid.prototype._findPrevFocusableCell = function(e, colIndex, rowIndex, focusableColIndices, content) {
4248
- let startIdx = focusableColIndices.indexOf(colIndex);
4249
- let len = focusableColIndices.length;
4268
+ Grid.prototype._focusPrevCellContent = function(args) {
4269
+ let colIndex = args.colIndex;
4270
+ let rowIndex = args.rowIndex;
4271
+ if(rowIndex < 0 || rowIndex == null) {
4272
+ return;
4273
+ }
4250
4274
 
4251
- // Calculate starting row and column index
4252
- if(!isValidTarget(e.target, this._hiddenInput) || startIdx < 0) {
4253
- rowIndex = 0;
4254
- startIdx = 0;
4255
- } else if(isValidInput(content) && startIdx >= 0) {
4256
- startIdx--;
4275
+ let focusableColIndices = args.focusableColIndices;
4276
+ let len = focusableColIndices.length;
4277
+ let startIdx = len - 1;
4278
+ let i;
4279
+ if(colIndex >= 0) {
4280
+ for(i = len - 1; --i >= 0;) {
4281
+ if(colIndex > focusableColIndices[i]) {
4282
+ break;
4283
+ }
4284
+ startIdx = i;
4285
+ }
4286
+ }
4287
+ // If the current focus is on a valid content, starts on the next cell
4288
+ if(args.event && args.validContent) {
4289
+ --startIdx;
4257
4290
  }
4258
4291
 
4259
4292
  let grid = this._grid;
@@ -4261,32 +4294,33 @@ Grid.prototype._findPrevFocusableCell = function(e, colIndex, rowIndex, focusabl
4261
4294
  let viewInfo = grid.getVerticalViewInfo();
4262
4295
  let topRowIndex = viewInfo.topRowIndex;
4263
4296
  for(let r = rowIndex; r >= 0; r--) {
4264
- for(let i = startIdx; i >= 0; i--) {
4297
+ for(i = startIdx; i >= 0; i--) {
4265
4298
  let c = focusableColIndices[i];
4266
4299
  if(r < topRowIndex) {
4267
- this._requestScroll(e, c, r, focusableColIndices, section);
4300
+ this._requestScroll(args, c, r);
4268
4301
  return;
4269
4302
  } else {
4270
4303
  let cell = section.getCell(c, r);
4271
4304
  if(focusCell(cell)) {
4272
- e.preventDefault();
4305
+ if(args.event) {
4306
+ args.event.preventDefault();
4307
+ }
4273
4308
  return;
4274
4309
  }
4275
4310
  }
4276
4311
  }
4277
4312
  startIdx = len - 1;
4278
4313
  }
4314
+
4315
+ if(args.validContent) { // The current focus on the last focusable content
4316
+ this._grid.getHiddenInput(true).focus();
4317
+ }
4279
4318
  };
4280
4319
 
4281
4320
  /** @private
4282
4321
  * @param {Object} e
4283
4322
  */
4284
- Grid.prototype._onKeyDown = function(e) {
4285
- if (e.keyCode !== 9 || e.ctrlKey || e.altKey || e.metaKey) {
4286
- return;
4287
- }
4288
-
4289
- // Find next focusable cell
4323
+ Grid.prototype._onTabNavigation = function(e) {
4290
4324
  let colDefs = this.getColumnDefinitions();
4291
4325
  let colCount = colDefs.length;
4292
4326
 
@@ -4302,13 +4336,36 @@ Grid.prototype._onKeyDown = function(e) {
4302
4336
  }
4303
4337
 
4304
4338
  this._scrolledRow = -1; // Reset the scroll loop protector
4305
- let pos = this.getRelativePosition(e);
4306
- let content = pos["cell"] ? pos["cell"].getContent() : null;
4339
+ let keyEvt = e.event;
4340
+ let pos = this.getRelativePosition(keyEvt);
4341
+ let validContent = true;
4342
+ let activeElement = e.activeElement;
4343
+ if(activeElement) {
4344
+ validContent = !activeElement.classList.contains("valigner");
4345
+ }
4346
+
4347
+ if(validContent) {
4348
+ let content = pos["cell"] ? pos["cell"].getContent() : null;
4349
+ validContent = isFocusableContent(content);
4350
+ }
4351
+ let startingRowIndex = pos["rowIndex"];
4352
+ if(e.onTheEdge) {
4353
+ let viewInfo = this._grid.getVScrollView();
4354
+ startingRowIndex = keyEvt.shiftKey ? viewInfo.lastFullRow : viewInfo.firstFullRow;
4355
+ }
4356
+ let args = {
4357
+ event: keyEvt,
4358
+ shiftKey: keyEvt.shiftKey,
4359
+ colIndex: pos["colIndex"],
4360
+ rowIndex: startingRowIndex,
4361
+ focusableColIndices: focusableColIndices,
4362
+ validContent: validContent
4363
+ };
4307
4364
 
4308
- if(e.shiftKey) {
4309
- this._findPrevFocusableCell(e, pos["colIndex"], pos["rowIndex"], focusableColIndices, content);
4365
+ if(keyEvt.shiftKey) {
4366
+ this._focusPrevCellContent(args);
4310
4367
  } else {
4311
- this._findNextFocusableCell(e, pos["colIndex"], pos["rowIndex"], focusableColIndices, content);
4368
+ this._focusNextCellContent(args);
4312
4369
  }
4313
4370
  };
4314
4371
 
@@ -50,6 +50,8 @@ declare class FilterInputPlugin extends GridPlugin {
50
50
 
51
51
  public setInputValue(colIndex: number, value: any): void;
52
52
 
53
+ public disableColumnInput(colIndex: number, disabled?: boolean|null): void;
54
+
53
55
  public refresh(delayMs?: number|null): void;
54
56
 
55
57
  public setFilterLogic(colIndex: number, func: ((...params: any[]) => any)|null, ctx?: any): void;
@@ -871,6 +871,25 @@ FilterInputPlugin.prototype.setInputValue = function (colIndex, value) {
871
871
  }
872
872
  };
873
873
  /** @public
874
+ * @param {number} colIndex
875
+ * @param {boolean=} disabled
876
+ */
877
+
878
+
879
+ FilterInputPlugin.prototype.disableColumnInput = function (colIndex, disabled) {
880
+ var inputElem = this.getColumnInput(colIndex);
881
+
882
+ if (inputElem) {
883
+ disabled = disabled != null ? disabled : true;
884
+
885
+ if (disabled) {
886
+ inputElem.setAttribute("disabled", "");
887
+ } else {
888
+ inputElem.removeAttribute("disabled");
889
+ }
890
+ }
891
+ };
892
+ /** @public
874
893
  * @ignore
875
894
  * @param {number} colIndex
876
895
  * @return {Object}
@@ -129,6 +129,10 @@ declare class RowFilteringPlugin extends GridPlugin {
129
129
 
130
130
  public enableSeparatorFiltering(enabled?: boolean|null): void;
131
131
 
132
+ public showColumnFilterIcon(colIndex: number, shown?: boolean|null): void;
133
+
134
+ public hideColumnFilterIcon(colIndex: number, hidden?: boolean|null): void;
135
+
132
136
  }
133
137
 
134
138
  declare function colSettings(colIndex: number, exp: RowFilteringPlugin.Expression|null, ctx?: (any|string)|null): boolean;
@@ -1333,8 +1333,11 @@ RowFilteringPlugin.prototype.refresh = function() {
1333
1333
  * @param {number} colIndex
1334
1334
  */
1335
1335
  RowFilteringPlugin.prototype._updateColumnIcon = function(colIndex) {
1336
- let cfo = this._getColumnFilterOption(colIndex); // colData["rowFiltering"]["filterOption"]
1337
1336
  let colSettings = this._getUserColumnSettings(colIndex); // colData["rowFiltering"]
1337
+ if(colSettings.hiddenIcon) {
1338
+ return;
1339
+ }
1340
+ let cfo = this._getColumnFilterOption(colIndex); // colData["rowFiltering"]["filterOption"]
1338
1341
  let iconActivation = colSettings.filterIcon == false ? "none" : this._iconActivation;
1339
1342
  let hasFilter = cfo ? cfo._filters.length : 0;
1340
1343
 
@@ -2267,6 +2270,38 @@ RowFilteringPlugin.prototype.enableSeparatorFiltering = function (enabled) {
2267
2270
  }
2268
2271
  };
2269
2272
 
2273
+ /**
2274
+ * @public
2275
+ * @param {number} colIndex
2276
+ * @param {boolean=} shown
2277
+ */
2278
+ RowFilteringPlugin.prototype.showColumnFilterIcon = function(colIndex, shown) {
2279
+ this.hideColumnFilterIcon(colIndex, shown == null ? false : !shown);
2280
+ };
2281
+ /**
2282
+ * @public
2283
+ * @param {number} colIndex
2284
+ * @param {boolean=} hidden
2285
+ */
2286
+ RowFilteringPlugin.prototype.hideColumnFilterIcon = function(colIndex, hidden) {
2287
+ hidden = hidden != null ? !!hidden : true;
2288
+ let colSettings = this._getUserColumnSettings(colIndex);
2289
+ if(colSettings.hiddenIcon !== hidden) {
2290
+ let cssVal = hidden ? "none" : "";
2291
+ let icons = this.getColumnFilterIcons(colIndex);
2292
+ for(let i = 0; i < icons.length; i++) {
2293
+ icons[i].style.display = cssVal;
2294
+ }
2295
+
2296
+ let filterInput = this._getPlugin("FilterInputPlugin", this._hosts[0]);
2297
+ if(filterInput && filterInput.disableColumnInput) {
2298
+ filterInput.disableColumnInput(colIndex, hidden);
2299
+ }
2300
+
2301
+ colSettings.hiddenIcon = hidden;
2302
+ }
2303
+ };
2304
+
2270
2305
 
2271
2306
 
2272
2307
  export default RowFilteringPlugin;
@@ -1,5 +1,5 @@
1
1
  import { TickCodes, TickFields } from "./TickCodes.js";
2
- import { rgb2Hex } from "./Util.js";
2
+ import { rgb2Hex, num2Hex, num2Rgb, hex2Num, hex2Rgb, blendColor, getContrastColor } from "./Color.js";
3
3
  import { ElfUtil } from "./ElfUtil.js";
4
4
  import { ExpressionParser } from "./ExpressionParser.js";
5
5
 
@@ -1,5 +1,5 @@
1
1
  import { TickCodes, TickFields } from "./TickCodes.js";
2
- import { rgb2Hex } from "./Util.js";
2
+ import { rgb2Hex, num2Hex, num2Rgb, hex2Num, hex2Rgb, blendColor, getContrastColor } from "./Color.js";
3
3
  import { ElfUtil } from "./ElfUtil.js";
4
4
  import { ExpressionParser } from "./ExpressionParser.js";
5
5
 
@@ -709,17 +709,17 @@ CellPainter.prototype._getStyles = function(rowData, min, max) {
709
709
  if(this._coloringType === CellPainter.ColoringTypes.HEATMAP) {
710
710
  let blendedColor;
711
711
  if(ret > 0) {
712
- blendedColor = CellPainter.blendColor(curCond["baseColor"], curCond["upColor"], ret);
712
+ blendedColor = blendColor(curCond["baseColor"], curCond["upColor"], ret);
713
713
  } else {
714
- blendedColor = CellPainter.blendColor(curCond["baseColor"], curCond["downColor"], -ret);
714
+ blendedColor = blendColor(curCond["baseColor"], curCond["downColor"], -ret);
715
715
  }
716
716
 
717
717
  if(curCond["textMode"]) {
718
- CellPainter._colorObj["color"] = CellPainter.num2Hex(blendedColor);
718
+ CellPainter._colorObj["color"] = num2Hex(blendedColor);
719
719
  return CellPainter._colorObj;
720
720
  } else {
721
- CellPainter._bgObj["backgroundColor"] = CellPainter.num2Hex(blendedColor);
722
- CellPainter._bgObj["color"] = CellPainter.blackAndWhite(blendedColor);
721
+ CellPainter._bgObj["backgroundColor"] = num2Hex(blendedColor);
722
+ CellPainter._bgObj["color"] = getContrastColor(blendedColor);
723
723
 
724
724
  return CellPainter._bgObj;
725
725
  }
@@ -751,94 +751,44 @@ CellPainter.prototype._getStyles = function(rowData, min, max) {
751
751
  };
752
752
 
753
753
  /** @public
754
+ * @function
754
755
  * @param {string} baseColor
755
756
  * @param {string} maxColor
756
757
  * @param {number} ratio [0, 1]
757
758
  * @return {Array.<number>} resultColor
758
759
  */
759
- CellPainter.blendColor = function (baseColor, maxColor, ratio) { // TODO: Optimize this
760
- if (ratio > 1) {
761
- ratio = 1;
762
- } else if(ratio < 0) {
763
- ratio = 0;
764
- }
765
-
766
- let baseColorTriplet = CellPainter.hex2Num(baseColor);
767
- let maxColorTriplet = CellPainter.hex2Num(maxColor);
768
- let blendResult = [];
769
- for (let i = 0; i < 3; ++i) {
770
- let gap = (maxColorTriplet[i] - baseColorTriplet[i]) * ratio;
771
- blendResult.push(baseColorTriplet[i] + gap);
772
- }
773
-
774
- return blendResult;
775
- };
776
-
777
- /** @private
778
- * @param {Array.<number>} triplet
779
- * @return {string} resultColor
780
- */
781
- CellPainter.blackAndWhite = function (triplet) {
782
- let brightness = Math.sqrt(triplet[0] * triplet[0] * 0.241 + triplet[1] * triplet[1] * 0.691 + triplet[2] * triplet[2] * 0.068);
783
-
784
- if (brightness >= 135) { // Brighter color has more impact to human eye than the darker color
785
- return '#000000';
786
- }
787
- return '#FFFFFF';
788
- };
789
-
760
+ CellPainter.blendColor = blendColor; // For backward compatability
790
761
  /** @public
791
762
  * @function
792
763
  * @param {string} rgbCode
793
764
  * @return {string} resultColor E.g. "#10FF0D"
794
765
  */
795
766
  CellPainter.rgb2Hex = rgb2Hex; // For backward compatability
796
-
797
767
  /** @public
798
768
  * @function
799
769
  * @param {Array.<number>} triplet
800
770
  * @return {string} resultColor
801
771
  */
802
- CellPainter.num2Hex = function (triplet) {
803
- let rgb = triplet[2] | (triplet[1] << 8) | (triplet[0] << 16);
804
- return ('#' + (0x1000000 + rgb).toString(16).slice(1));
805
- };
772
+ CellPainter.num2Hex = num2Hex; // For backward compatability
806
773
  /** Note that Chrome, IE, and Firefox store color in rgb representation.
807
774
  * @public
808
775
  * @function
809
776
  * @param {Array.<number>} triplet
810
777
  * @return {string} Color string in RGB represetation (e.g. rgb(100, 44, 1))
811
778
  */
812
- CellPainter.num2Rgb = function (triplet) {
813
- return 'rgb(' + triplet[0] + ', ' + triplet[1] + ', ' + triplet[2] + ')';
814
- };
779
+ CellPainter.num2Rgb = num2Rgb; // For backward compatability
815
780
  /** @public
816
781
  * @function
817
782
  * @param {string} hex
818
783
  * @return {Array.<number>} array of size 3 which contains [red, green, blue]
819
784
  */
820
- CellPainter.hex2Num = function (hex) {
821
- let hexInt = parseInt(hex.replace(/[^0-9A-F]/gi, ''), 16);
822
- let r = (hexInt >> 16) & 255;
823
- let g = (hexInt >> 8) & 255;
824
- let b = hexInt & 255;
825
- return [r, g, b];
826
- };
785
+ CellPainter.hex2Num = hex2Num; // For backward compatability
827
786
  /** @public
828
787
  * @function
829
788
  * @param {string} hex Color string with leading # character (e.g. #FFAA00)
830
789
  * @return {string} Color string in RGB represetation (e.g. rgb(100, 44, 1))
831
790
  */
832
- CellPainter.hex2Rgb = function (hex) {
833
- if(hex) {
834
- let hexInt = parseInt(hex.replace(/[^0-9A-F]/gi, ''), 16);
835
- let r = (hexInt >> 16) & 255;
836
- let g = (hexInt >> 8) & 255;
837
- let b = hexInt & 255;
838
- return 'rgb(' + r + ', ' + g + ', ' + b + ')';
839
- }
840
- return '';
841
- };
791
+ CellPainter.hex2Rgb = hex2Rgb; // For backward compatability
842
792
 
843
793
  /** Deprecated. Colors should be changed according to user's settings by CellPainter#loadThemeColors
844
794
  * @private
@@ -974,11 +924,11 @@ CellPainter._clearBlinkTimer = function(scp, opt_restoreColor) {
974
924
  CellPainter.getOppositeColor = function (hexCode) {
975
925
  if(typeof hexCode === "string") {
976
926
  if(hexCode.charAt(0) === "#") {
977
- let triplet = CellPainter.hex2Num(hexCode);
978
- return CellPainter.blackAndWhite(triplet);
927
+ let triplet = hex2Num(hexCode);
928
+ return getContrastColor(triplet);
979
929
  }
980
930
  } else if(Array.isArray(hexCode)) {
981
- return CellPainter.blackAndWhite(hexCode);
931
+ return getContrastColor(hexCode);
982
932
  }
983
933
  return "";
984
934
  };