Skip to content

Commit

Permalink
fix(filter): changing Slider dynamically shouldn't display tooltip (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
ghiscoding authored Jun 28, 2024
1 parent 603263e commit 34bdf76
Show file tree
Hide file tree
Showing 6 changed files with 65 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ const gridStub = {
render: jest.fn(),
onHeaderMouseLeave: new SlickEvent(),
onHeaderRowMouseEnter: new SlickEvent(),
onHeaderRowMouseLeave: new SlickEvent(),
} as unknown as SlickGrid;

describe('CompoundSliderFilter', () => {
Expand Down Expand Up @@ -107,6 +108,7 @@ describe('CompoundSliderFilter', () => {
it('should call "setValues" with "operator" set in the filter arguments and expect that value to be converted to number and in the callback when triggered', () => {
const callbackSpy = jest.spyOn(filterArguments, 'callback');
const rowMouseEnterSpy = jest.spyOn(gridStub.onHeaderRowMouseEnter, 'notify');
const rowMouseLeaveSpy = jest.spyOn(gridStub.onHeaderRowMouseLeave, 'notify');
const filterArgs = { ...filterArguments, operator: '>', grid: gridStub } as FilterArguments;

filter.init(filterArgs);
Expand All @@ -116,6 +118,7 @@ describe('CompoundSliderFilter', () => {

expect(callbackSpy).toHaveBeenLastCalledWith(expect.anything(), { columnDef: mockColumn, operator: '>', searchTerms: [2], shouldTriggerQuery: true });
expect(rowMouseEnterSpy).toHaveBeenCalledWith({ column: mockColumn, grid: gridStub }, expect.anything());
expect(rowMouseLeaveSpy).toHaveBeenCalledWith({ column: mockColumn, grid: gridStub });
});

it('should trigger an slider input change event and expect slider value to be updated and also "onHeaderRowMouseEnter" to be notified', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ const gridStub = {
render: jest.fn(),
onHeaderMouseLeave: new SlickEvent(),
onHeaderRowMouseEnter: new SlickEvent(),
onHeaderRowMouseLeave: new SlickEvent(),
} as unknown as SlickGrid;

describe('SingleSliderFilter', () => {
Expand Down Expand Up @@ -77,6 +78,7 @@ describe('SingleSliderFilter', () => {
it('should call "setValues" and expect that value, converted as a number, to be in the callback when triggered', () => {
const callbackSpy = jest.spyOn(filterArgs, 'callback');
const rowMouseEnterSpy = jest.spyOn(gridStub.onHeaderRowMouseEnter, 'notify');
const rowMouseLeaveSpy = jest.spyOn(gridStub.onHeaderRowMouseLeave, 'notify');

filter.init(filterArgs);
filter.setValues(['2']);
Expand All @@ -85,6 +87,7 @@ describe('SingleSliderFilter', () => {

expect(callbackSpy).toHaveBeenLastCalledWith(new Event('change'), { columnDef: mockColumn, operator: 'GE', searchTerms: [2], shouldTriggerQuery: true });
expect(rowMouseEnterSpy).toHaveBeenCalledWith({ column: mockColumn, grid: gridStub }, expect.anything());
expect(rowMouseLeaveSpy).toHaveBeenCalledWith({ column: mockColumn, grid: gridStub });
});

it('should trigger an slider input change event and expect slider value to be updated and also "onHeaderRowMouseEnter" to be notified', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ const gridStub = {
render: jest.fn(),
onHeaderMouseLeave: new SlickEvent(),
onHeaderRowMouseEnter: new SlickEvent(),
onHeaderRowMouseLeave: new SlickEvent(),
} as unknown as SlickGrid;

describe('SliderRangeFilter', () => {
Expand Down Expand Up @@ -120,6 +121,7 @@ describe('SliderRangeFilter', () => {
it('should call "setValues" and expect that value to be in the callback when triggered', () => {
const callbackSpy = jest.spyOn(filterArguments, 'callback');
const rowMouseEnterSpy = jest.spyOn(gridStub.onHeaderRowMouseEnter, 'notify');
const rowMouseLeaveSpy = jest.spyOn(gridStub.onHeaderRowMouseLeave, 'notify');

filter.init(filterArguments);
filter.setValues(['2..80']);
Expand All @@ -128,6 +130,7 @@ describe('SliderRangeFilter', () => {

expect(callbackSpy).toHaveBeenLastCalledWith(expect.anything(), { columnDef: mockColumn, operator: 'RangeInclusive', searchTerms: [2, 80], shouldTriggerQuery: true });
expect(rowMouseEnterSpy).toHaveBeenCalledWith({ column: mockColumn, grid: gridStub }, expect.anything());
expect(rowMouseLeaveSpy).toHaveBeenCalledWith({ column: mockColumn, grid: gridStub });
});

it('should trigger an slider input change event and expect slider value to be updated and also "onHeaderRowMouseEnter" to be notified', () => {
Expand Down
33 changes: 22 additions & 11 deletions packages/common/src/filters/sliderFilter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import type {
Column,
ColumnFilter,
CurrentSliderOption,
DOMEvent,
Filter,
FilterArguments,
FilterCallback,
Expand Down Expand Up @@ -182,12 +183,22 @@ export class SliderFilter implements Filter {
* @param leftValue number
* @param rightValue number
*/
renderSliderValues(leftValue?: number | string | undefined, rightValue?: number | string | undefined): void {
if (this._leftSliderNumberElm?.textContent && leftValue) {
this._leftSliderNumberElm.textContent = leftValue.toString();
renderSliderValues(leftValue?: number | string, rightValue?: number | string, triggerTooltipMouseLeave = true): void {
const leftVal = leftValue?.toString() || '';
const rightVal = rightValue?.toString() || '';

if (this._leftSliderNumberElm?.textContent) {
this._leftSliderNumberElm.textContent = leftVal;
}
if (this._rightSliderNumberElm?.textContent) {
this._rightSliderNumberElm.textContent = rightVal;
}
if (this._rightSliderNumberElm?.textContent && rightValue) {
this._rightSliderNumberElm.textContent = rightValue.toString();
this._sliderRangeContainElm.title = this.sliderType === 'double' ? `${leftVal} - ${rightVal}` : `${rightVal}`;

// when changing slider values dynamically (typically via a button), we'll want to avoid tooltips showing up
// onHeaderRowMouseLeave will hide any tooltip
if (triggerTooltipMouseLeave) {
this.grid.onHeaderRowMouseLeave.notify({ column: this.columnDef, grid: this.grid });
}
}

Expand Down Expand Up @@ -363,13 +374,13 @@ export class SliderFilter implements Filter {

// attach events
this._bindEventService.bind(this._sliderTrackElm, 'click', this.sliderTrackClicked.bind(this) as EventListener);
this._bindEventService.bind(this._sliderRightInputElm, ['input', 'change'], this.slideRightInputChanged.bind(this));
this._bindEventService.bind(this._sliderRightInputElm, ['input', 'change'], this.slideRightInputChanged.bind(this) as EventListener);
this._bindEventService.bind(this._sliderRightInputElm, ['change', 'mouseup', 'touchend'], this.onValueChanged.bind(this) as EventListener);

if (this.sliderType === 'compound' && this._selectOperatorElm) {
this._bindEventService.bind(this._selectOperatorElm, ['change'], this.onValueChanged.bind(this) as EventListener);
} else if (this.sliderType === 'double' && this._sliderLeftInputElm) {
this._bindEventService.bind(this._sliderLeftInputElm, ['input', 'change'], this.slideLeftInputChanged.bind(this));
this._bindEventService.bind(this._sliderLeftInputElm, ['input', 'change'], this.slideLeftInputChanged.bind(this) as EventListener);
this._bindEventService.bind(this._sliderLeftInputElm, ['change', 'mouseup', 'touchend'], this.onValueChanged.bind(this) as EventListener);
}

Expand All @@ -392,7 +403,7 @@ export class SliderFilter implements Filter {
}

/** handle value change event triggered, trigger filter callback & update "filled" class name */
protected onValueChanged(e: MouseEvent): void {
protected onValueChanged(e: DOMEvent<HTMLInputElement>): void {
const sliderRightVal = parseInt(this._sliderRightInputElm?.value ?? '', 10);
let value;
let searchTerms: SearchTerm[];
Expand Down Expand Up @@ -443,7 +454,7 @@ export class SliderFilter implements Filter {
this._sliderRightInputElm?.classList[addRemoveCmd]('focus');
}

protected slideLeftInputChanged(e: Event): void {
protected slideLeftInputChanged(e: DOMEvent<HTMLInputElement>): void {
const sliderLeftVal = parseInt(this._sliderLeftInputElm?.value ?? '', 10);
const sliderRightVal = parseInt(this._sliderRightInputElm?.value ?? '', 10);

Expand All @@ -467,7 +478,7 @@ export class SliderFilter implements Filter {
this.sliderLeftOrRightChanged(e, sliderLeftVal, sliderRightVal);
}

protected slideRightInputChanged(e: Event): void {
protected slideRightInputChanged(e: DOMEvent<HTMLInputElement>): void {
const sliderLeftVal = parseInt(this._sliderLeftInputElm?.value ?? '', 10);
const sliderRightVal = parseInt(this._sliderRightInputElm?.value ?? '', 10);

Expand All @@ -478,7 +489,7 @@ export class SliderFilter implements Filter {
this.sliderLeftOrRightChanged(e, sliderLeftVal, sliderRightVal);
}

protected sliderLeftOrRightChanged(e: Event, sliderLeftVal: number, sliderRightVal: number): void {
protected sliderLeftOrRightChanged(e: DOMEvent<HTMLInputElement>, sliderLeftVal: number, sliderRightVal: number): void {
this.updateTrackFilledColorWhenEnabled();
this.changeBothSliderFocuses(true);
this._sliderRangeContainElm.title = this.sliderType === 'double' ? `${sliderLeftVal} - ${sliderRightVal}` : `${sliderRightVal}`;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ const gridStub = {
onHeaderMouseOver: new SlickEvent(),
onHeaderRowMouseEnter: new SlickEvent(),
onHeaderRowMouseOver: new SlickEvent(),
onHeaderRowMouseLeave: new SlickEvent(),
onMouseLeave: new SlickEvent(),
onHeaderMouseOut: new SlickEvent(),
onHeaderRowMouseOut: new SlickEvent(),
Expand Down Expand Up @@ -309,7 +310,7 @@ describe('SlickCustomTooltip plugin', () => {
expect(tooltipElm.classList.contains('arrow-left-align')).toBeTruthy();
});

it('should create a tooltip as regular tooltip with coming from text content when it is filled & also expect "hideTooltip" to be called after leaving the cell when "onHeaderMouseOut" event is triggered', () => {
it('should create a tooltip as regular tooltip with coming from text content when it is filled & also expect "hideTooltip" to be called after leaving the cell when "onMouseLeave" event is triggered', () => {
const cellNode = document.createElement('div');
cellNode.className = 'slick-cell l2 r2';
cellNode.textContent = 'some text content';
Expand Down Expand Up @@ -339,6 +340,36 @@ describe('SlickCustomTooltip plugin', () => {
expect(hideColumnSpy).toHaveBeenCalled();
});

it('should create a tooltip as regular tooltip with coming from text content when it is filled & also expect "hideTooltip" to be called after leaving the cell when "onHeaderRowMouseLeave" event is triggered', () => {
const cellNode = document.createElement('div');
cellNode.className = 'slick-cell l2 r2';
cellNode.textContent = 'some text content';
cellNode.setAttribute('title', 'tooltip text');
Object.defineProperty(cellNode, 'scrollWidth', { writable: true, configurable: true, value: 400 });
const mockColumns = [{ id: 'firstName', field: 'firstName' }] as Column[];
jest.spyOn(gridStub, 'getCellFromEvent').mockReturnValue({ cell: 0, row: 1 });
jest.spyOn(gridStub, 'getCellNode').mockReturnValue(cellNode);
jest.spyOn(gridStub, 'getColumns').mockReturnValue(mockColumns);
jest.spyOn(dataviewStub, 'getItem').mockReturnValue({ firstName: 'John', lastName: 'Doe' });
const hideColumnSpy = jest.spyOn(plugin, 'hideTooltip');

plugin.init(gridStub, container);
plugin.setOptions({ useRegularTooltip: true, maxWidth: 85 });
gridStub.onMouseEnter.notify({ grid: gridStub } as any, { ...new SlickEventData(), target: cellNode } as any);

const tooltipElm = document.body.querySelector('.slick-custom-tooltip') as HTMLDivElement;
expect(tooltipElm).toBeTruthy();
expect(tooltipElm).toEqual(plugin.tooltipElm);
expect(plugin.addonOptions).toBeTruthy();
expect(tooltipElm.style.maxWidth).toBe('85px');
expect(tooltipElm.textContent).toBe('some text content');
expect(tooltipElm.classList.contains('arrow-down')).toBeTruthy();
expect(tooltipElm.classList.contains('arrow-left-align')).toBeTruthy();

gridStub.onHeaderRowMouseLeave.notify({ grid: gridStub } as any);
expect(hideColumnSpy).toHaveBeenCalled();
});

it('should create a tooltip as regular tooltip with truncated text when tooltip option has "useRegularTooltip" enabled and the tooltip text is longer than that of "tooltipTextMaxLength"', () => {
const cellNode = document.createElement('div');
cellNode.className = 'slick-cell l2 r2';
Expand Down
3 changes: 2 additions & 1 deletion packages/custom-tooltip-plugin/src/slickCustomTooltip.ts
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@ export class SlickCustomTooltip {
.subscribe(grid.onHeaderRowMouseOver, (e, args) => this.handleOnHeaderMouseOverByType(e, args, 'slick-headerrow-column'))
.subscribe(grid.onMouseLeave, this.hideTooltip.bind(this))
.subscribe(grid.onHeaderMouseOut, this.hideTooltip.bind(this))
.subscribe(grid.onHeaderRowMouseLeave, this.hideTooltip.bind(this))
.subscribe(grid.onHeaderRowMouseOut, this.hideTooltip.bind(this));
}

Expand Down Expand Up @@ -221,7 +222,7 @@ export class SlickCustomTooltip {
const isHeaderRowType = selector === 'slick-headerrow-column';

// run the override function (when defined), if the result is false it won't go further
args = args || {};
args ||= {};
args.cell = cell.cell;
args.row = cell.row;
args.columnDef = columnDef;
Expand Down

0 comments on commit 34bdf76

Please sign in to comment.