@refinitiv-ui/efx-grid 6.0.108 → 6.0.110

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
  };