Skip to content

Commit

Permalink
Merge branch 'v3' of github.com:owlsdepartment/ovee into v3
Browse files Browse the repository at this point in the history
  • Loading branch information
F0rsaken committed Jun 2, 2024
2 parents adfd241 + 7ebad84 commit acb31ec
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 15 deletions.
9 changes: 5 additions & 4 deletions docs/guide/usage/event-handling.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,11 @@ export const MyComponent = defineComponent((element, { on }) => {

And that's it! You don't need to clear this event. Once the component is destroyed, all listeners are removed as well. Notice that we didn't refer to the element. When you don't specify a target, `on` assumes that you want to connect it to the component's root. It also doesn't need any special context and can be called anytime, from any place possible.

The third argument, `ListenerOptions`, allows for some more customization. It is an object similar to options passed to `addEventListener` ([MDN documentation](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#options)) with three new fields:
- `target: string | EventTarget | EventTarget[]` - specify a target element. It can be a query selector string or element instance. It also accepts an array of elements
- `root: boolean` - if you specify `root: true` without using `target`, events will be connected to the root document element. If the `target` is a `string` and the `root` equals `true`, then elements will be searched relatively to the whole document. In other cases, `querySelector` will be run relatively to the components element.
- `multiple: boolean` - when set to true and the `target` is a string, it will connect the listener to all elements matching the selector. Otherwise, it will match to the first one found
The third argument, `ListenerOptions`, allows for some more customization. It is an object similar to options passed to `addEventListener` ([MDN documentation](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#options)) with new fields:
- `target?: string | EventTarget | EventTarget[]` - specify a target element. It can be a query selector string or element instance. It also accepts an array of elements
- `root?: boolean` - if you specify `root: true` without using `target`, events will be connected to the root document element. If the `target` is a `string` and the `root` equals `true`, then elements will be searched relatively to the whole document. In other cases, `querySelector` will be run relatively to the components element.
- `multiple?: boolean` - when set to true and the `target` is a string, it will connect the listener to all elements matching the selector. Otherwise, it will match to the first one found
- `optional?: boolean` - if set to true, no error is logged, when matching element isn't found

So to add a `click` handler to all nested buttons you should write:

Expand Down
32 changes: 21 additions & 11 deletions packages/ovee/src/dom/EventDelegate.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { NOOP } from '@/constants';
import { Logger } from '@/errors';
import { isString, omit } from '@/utils';

Expand All @@ -13,6 +14,7 @@ export interface TargetOptions {
target?: Target;
root?: true;
multiple?: boolean;
optional?: boolean;
}

export interface ListenerOptions extends AddEventListenerOptions, TargetOptions {}
Expand Down Expand Up @@ -41,6 +43,10 @@ export class EventDelegate<Context = any> {
const { targetOption, target } = this.getTarget(options);
const removeListeners: Array<() => void> = [];

if (!target) {
return NOOP;
}

events.split(' ').forEach(event => {
const handler = (...args: any[]) => callback.apply(this.context, args);
const targets = Array.isArray(target) ? target : [target];
Expand Down Expand Up @@ -90,11 +96,11 @@ export class EventDelegate<Context = any> {
}

private getTarget(options?: TargetOptions): {
target: EventTarget | EventTarget[];
target: EventTarget | EventTarget[] | null;
targetOption: Target;
} {
const targetOption = options?.target ?? this.targetElement;
let target: EventTarget | EventTarget[];
let target: EventTarget | EventTarget[] | null;

if (isString(targetOption)) {
const isAbsolute = options?.root;
Expand All @@ -105,16 +111,20 @@ export class EventDelegate<Context = any> {
: selectorBase.querySelector(targetOption);

if (!newTarget || (Array.isArray(newTarget) && !newTarget.length)) {
const errorMessage = `Could not find element${
multipleTargets ? 's' : ''
} with selector '${targetOption}' ${
isAbsolute ? 'in document' : 'relatively to current element'
}`;

throw Error(logger.getMessage(errorMessage));
if (!options?.optional) {
const errorMessage = `Could not find element${
multipleTargets ? 's' : ''
} with selector '${targetOption}' ${
isAbsolute ? 'in document' : 'relatively to current element'
}`;

logger.error(errorMessage);
}

target = null;
} else {
target = newTarget;
}

target = newTarget;
} else {
target = targetOption;
}
Expand Down

0 comments on commit acb31ec

Please sign in to comment.