Skip to content

Commit

Permalink
Supercharge TooltipView so it can be attached to subelements (#448 #447)
Browse files Browse the repository at this point in the history
  • Loading branch information
jgonggrijp committed Jun 13, 2022
1 parent a485531 commit a274d89
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 6 deletions.
39 changes: 39 additions & 0 deletions frontend/src/tooltip/tooltip-view-test.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { each } from 'lodash';

import { enableI18n, event } from '../test-util';

import View from '../core/view';
Expand Down Expand Up @@ -85,4 +87,41 @@ describe('Tooltip', function () {
this.substrate.remove();
expect(view.remove).toHaveBeenCalled();
});

it('can be attached to multiple subelements of another view', function() {
const v1 = attachTooltip(this.substrate, {model: this.item}, 'ul');
const v2 = attachTooltip(this.substrate, {model: this.item}, 'li:first-child');
const v3 = attachTooltip(this.substrate, {model: this.item}, '#x');
const e3 = this.substrate.$('#x');
each([v1, v2, v3], view => spyOn(view, 'remove').and.callThrough());
const expectActive = (active, inactive) => {
each(active, v => expect(v.el).toHaveClass('is-tooltip-active'));
each(inactive, v => expect(v.el).not.toHaveClass('is-tooltip-active'));
};
this.substrate.$el.trigger('mouseenter');
expectActive([], [v1, v2, v3]);
this.substrate.$('ul').trigger('mouseenter');
expectActive([v1], [v2, v3]);
this.substrate.$('li:first-child').trigger('mouseenter');
expectActive([v1, v2], [v3]);
this.substrate.$('li:first-child').trigger('mouseleave');
this.substrate.$('li:nth-child(2)').trigger('mouseenter');
expectActive([v1, v3], [v2]);
each(['offset', 'width', 'height'], dimension =>
expect(v3.$el[dimension]()).toEqual(e3[dimension]())
);
this.substrate.$('li:nth-child(2)').trigger('mouseleave');
// We don't specify an expectation for v1 on the next line, because
// jQuery's .trigger method treats 'mouseenter' and 'mouseleave' as
// regular bubbling events, unlike what we expect with real mouse
// pointer interactions. Hence, we would "naturally" expect `v1` to be
// active, but in this spec, it would be inactive. Fortunately, it does
// not matter whether the test is accurate or not in this regard; it is
// reasonable to expect elements with tooltips to be disjoint.
expectActive([], [v2, v3]);
this.substrate.$('ul').trigger('mouseleave');
expectActive([], [v1, v2, v3]);
this.substrate.remove();
each([v1, v2, v3], v => expect(v.remove).toHaveBeenCalled());
});
});
12 changes: 6 additions & 6 deletions frontend/src/tooltip/tooltip-view.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,8 @@ export class Tooltip extends View<FlatItem> {
return this;
}

positionTo<V extends BView<any>>(view: V): this {
const other = view.$el;
positionTo<V extends BView<any>>(view: V, selector: string): this {
const other = selector ? view.$(selector) : view.$el;
const offset = other.offset();
const width = other.width();
const height = other.height();
Expand Down Expand Up @@ -107,14 +107,14 @@ extend(Tooltip.prototype, {
* taken care of and the tooltip is `.remove`d automatically when `view` is.
*/
export default function attachTooltip<V extends BView<any>>(
view: V, options: ViewOptions
view: V, options: ViewOptions, selector: string = ''
): Tooltip {
const tooltip = new Tooltip(options);
tooltip.$el.appendTo(document.body);
const openTooltip = () => tooltip.positionTo(view).show();
const openTooltip = () => tooltip.positionTo(view, selector).show();
function attachEvents() {
view.delegate('mouseenter', '', openTooltip);
view.delegate('mouseleave', '', tooltip.hide.bind(tooltip));
view.delegate('mouseenter', selector, openTooltip);
view.delegate('mouseleave', selector, tooltip.hide.bind(tooltip));
}
attachEvents();
const { remove, setElement } = view;
Expand Down

0 comments on commit a274d89

Please sign in to comment.