mirror of
https://github.com/philomena-dev/philomena.git
synced 2024-11-23 20:18:00 +01:00
Merge pull request #351 from philomena-dev/mouse-move-then-over
Add mouseMoveThenOver, test
This commit is contained in:
commit
c83b9f1833
3 changed files with 64 additions and 23 deletions
|
@ -8,6 +8,7 @@ import { getTermContexts } from './match_query';
|
||||||
import store from './utils/store';
|
import store from './utils/store';
|
||||||
import { TermContext } from './query/lex.ts';
|
import { TermContext } from './query/lex.ts';
|
||||||
import { $, $$, makeEl, removeEl } from './utils/dom.ts';
|
import { $, $$, makeEl, removeEl } from './utils/dom.ts';
|
||||||
|
import { mouseMoveThenOver } from './utils/events.ts';
|
||||||
|
|
||||||
type TermSuggestion = {
|
type TermSuggestion = {
|
||||||
label: string;
|
label: string;
|
||||||
|
@ -125,38 +126,18 @@ function createItem(list: HTMLUListElement, suggestion: TermSuggestion) {
|
||||||
className: 'autocomplete__item',
|
className: 'autocomplete__item',
|
||||||
});
|
});
|
||||||
|
|
||||||
let ignoreMouseOver = true;
|
|
||||||
|
|
||||||
item.textContent = suggestion.label;
|
item.textContent = suggestion.label;
|
||||||
item.dataset.value = suggestion.value;
|
item.dataset.value = suggestion.value;
|
||||||
|
|
||||||
function onItemMouseOver() {
|
mouseMoveThenOver(item, () => {
|
||||||
// Prevent selection when mouse entered the element without actually moving.
|
|
||||||
if (ignoreMouseOver) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
removeSelected();
|
removeSelected();
|
||||||
item.classList.add('autocomplete__item--selected');
|
item.classList.add('autocomplete__item--selected');
|
||||||
}
|
});
|
||||||
|
|
||||||
item.addEventListener('mouseover', onItemMouseOver);
|
|
||||||
|
|
||||||
item.addEventListener('mouseout', () => {
|
item.addEventListener('mouseout', () => {
|
||||||
removeSelected();
|
removeSelected();
|
||||||
});
|
});
|
||||||
|
|
||||||
item.addEventListener(
|
|
||||||
'mousemove',
|
|
||||||
() => {
|
|
||||||
ignoreMouseOver = false;
|
|
||||||
onItemMouseOver();
|
|
||||||
},
|
|
||||||
{
|
|
||||||
once: true,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
item.addEventListener('click', () => {
|
item.addEventListener('click', () => {
|
||||||
if (!inputField || !item.dataset.value) return;
|
if (!inputField || !item.dataset.value) return;
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { delegate, fire, leftClick, on, PhilomenaAvailableEventsMap } from '../events';
|
import { delegate, fire, mouseMoveThenOver, leftClick, on, PhilomenaAvailableEventsMap } from '../events';
|
||||||
import { getRandomArrayItem } from '../../../test/randomness';
|
import { getRandomArrayItem } from '../../../test/randomness';
|
||||||
import { fireEvent } from '@testing-library/dom';
|
import { fireEvent } from '@testing-library/dom';
|
||||||
|
|
||||||
|
@ -80,6 +80,55 @@ describe('Event utils', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('mouseMoveThenOver', () => {
|
||||||
|
it('should NOT fire on first mouseover', () => {
|
||||||
|
const mockButton = document.createElement('button');
|
||||||
|
const mockHandler = vi.fn();
|
||||||
|
|
||||||
|
mouseMoveThenOver(mockButton, mockHandler);
|
||||||
|
|
||||||
|
fireEvent.mouseOver(mockButton);
|
||||||
|
|
||||||
|
expect(mockHandler).toHaveBeenCalledTimes(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should fire on the first mousemove', () => {
|
||||||
|
const mockButton = document.createElement('button');
|
||||||
|
const mockHandler = vi.fn();
|
||||||
|
|
||||||
|
mouseMoveThenOver(mockButton, mockHandler);
|
||||||
|
|
||||||
|
fireEvent.mouseMove(mockButton);
|
||||||
|
|
||||||
|
expect(mockHandler).toHaveBeenCalledTimes(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should fire on subsequent mouseover', () => {
|
||||||
|
const mockButton = document.createElement('button');
|
||||||
|
const mockHandler = vi.fn();
|
||||||
|
|
||||||
|
mouseMoveThenOver(mockButton, mockHandler);
|
||||||
|
|
||||||
|
fireEvent.mouseMove(mockButton);
|
||||||
|
fireEvent.mouseOver(mockButton);
|
||||||
|
|
||||||
|
expect(mockHandler).toHaveBeenCalledTimes(2);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should NOT fire on subsequent mousemove', () => {
|
||||||
|
const mockButton = document.createElement('button');
|
||||||
|
const mockHandler = vi.fn();
|
||||||
|
|
||||||
|
mouseMoveThenOver(mockButton, mockHandler);
|
||||||
|
|
||||||
|
fireEvent.mouseMove(mockButton);
|
||||||
|
fireEvent.mouseOver(mockButton);
|
||||||
|
fireEvent.mouseMove(mockButton);
|
||||||
|
|
||||||
|
expect(mockHandler).toHaveBeenCalledTimes(2);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('delegate', () => {
|
describe('delegate', () => {
|
||||||
it('should call the native addEventListener method on the element', () => {
|
it('should call the native addEventListener method on the element', () => {
|
||||||
const mockElement = document.createElement('div');
|
const mockElement = document.createElement('div');
|
||||||
|
|
|
@ -43,6 +43,17 @@ export function leftClick<E extends MouseEvent, Target extends EventTarget>(func
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function mouseMoveThenOver<El extends HTMLElement>(element: El, func: (e: MouseEvent) => void) {
|
||||||
|
element.addEventListener(
|
||||||
|
'mousemove',
|
||||||
|
(event: MouseEvent) => {
|
||||||
|
func(event);
|
||||||
|
element.addEventListener('mouseover', func);
|
||||||
|
},
|
||||||
|
{ once: true },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
export function delegate<K extends keyof PhilomenaAvailableEventsMap, Target extends Element>(
|
export function delegate<K extends keyof PhilomenaAvailableEventsMap, Target extends Element>(
|
||||||
node: PhilomenaEventElement,
|
node: PhilomenaEventElement,
|
||||||
event: K,
|
event: K,
|
||||||
|
|
Loading…
Reference in a new issue