Skip to content

Commit

Permalink
Add elementFilter option
Browse files Browse the repository at this point in the history
  • Loading branch information
hmarr committed Dec 18, 2020
1 parent 1f67984 commit 8ffe945
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 17 deletions.
11 changes: 11 additions & 0 deletions example/example.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { ElementPicker } from "pick-dom-element";
function main() {
const status = document.getElementById("status");
const startButton = document.getElementById("start");
const onlyEmphasisCheckbox = document.getElementById("only-emphasis");

const setElement = (el) => {
const tags = [];
Expand All @@ -17,6 +18,10 @@ function main() {
};

const picker = new ElementPicker();
let onlyEmphasis = onlyEmphasisCheckbox.checked;
onlyEmphasisCheckbox.onchange = (ev) => {
onlyEmphasis = ev.target.checked;
}
const start = () => {
startButton.disabled = true;
picker.start({
Expand All @@ -25,6 +30,12 @@ function main() {
picker.stop();
startButton.disabled = false;
},
elementFilter: (el) => {
if (!onlyEmphasis) {
return true;
}
return ['I', 'B'].includes(el.tagName);
}
});
};

Expand Down
1 change: 1 addition & 0 deletions example/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,6 @@ <h1>Element Picker example</h1>
</p>
<div id="status">Click "start" to activate the picker.</div>
<button id="start">Start</button>
<label><input id="only-emphasis" type="checkbox" /> Only emphasis tags</label>
</body>
</html>
1 change: 1 addition & 0 deletions src/element-overlay.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ export default class ElementOverlay {
}

removeFromDOM() {
this.setBounds({ x: 0, y: 0, width: 0, height: 0 });
this.overlay.remove();
if (this.usingShadowDOM) {
this.shadowContainer.remove();
Expand Down
57 changes: 40 additions & 17 deletions src/element-picker.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import ElementOverlay from "./element-overlay";
import { getElementBounds } from "./utils";

type ElementCallback = (el: HTMLElement) => void;
type ElementCallback<T> = (el: HTMLElement) => T;
type ElementPickerOptions = {
parentElement?: Node;
useShadowDOM?: boolean;
onClick?: ElementCallback;
onHover?: ElementCallback;
onClick?: ElementCallback<void>;
onHover?: ElementCallback<void>;
elementFilter?: ElementCallback<boolean>;
};

export default class ElementPicker {
Expand Down Expand Up @@ -50,6 +51,9 @@ export default class ElementPicker {
document.removeEventListener("click", this.handleClick, true);

this.overlay.removeFromDOM();
this.target = undefined;
this.mouseX = undefined;
this.mouseY = undefined;

if (this.tickReq) {
window.cancelAnimationFrame(this.tickReq);
Expand All @@ -69,24 +73,43 @@ export default class ElementPicker {
};

private tick = () => {
if (this.mouseX && this.mouseY) {
this.overlay.ignoreCursor();
const elAtCursor = document.elementFromPoint(this.mouseX, this.mouseY);
const newTarget = elAtCursor as HTMLElement;
this.overlay.captureCursor();
this.updateTarget();
this.tickReq = window.requestAnimationFrame(this.tick);
};

private updateTarget() {
if (this.mouseX === undefined || this.mouseY === undefined) {
return;
}

if (newTarget && newTarget !== this.target) {
this.target = newTarget;
// Peek through the overlay to find the new target
this.overlay.ignoreCursor();
const elAtCursor = document.elementFromPoint(this.mouseX, this.mouseY);
const newTarget = elAtCursor as HTMLElement;
this.overlay.captureCursor();

const bounds = getElementBounds(newTarget);
this.overlay.setBounds(bounds);
// If the target hasn't changed, there's nothing to do
if (!newTarget || newTarget === this.target) {
return;
}

if (this.options?.onHover) {
this.options.onHover(newTarget);
}
// If we have an element filter and the new target doesn't match,
// clear out the target
if (this.options?.elementFilter) {
if (!this.options.elementFilter(newTarget)) {
this.target = undefined;
this.overlay.setBounds({ x: 0, y: 0, width: 0, height: 0 });
return;
}
}

this.tickReq = window.requestAnimationFrame(this.tick);
};
this.target = newTarget;

const bounds = getElementBounds(newTarget);
this.overlay.setBounds(bounds);

if (this.options?.onHover) {
this.options.onHover(newTarget);
}
}
}

0 comments on commit 8ffe945

Please sign in to comment.