Projects / Libraries / Tokan.js
Tokan ("特観", "とくかん") is a Japanese compound word where "特" (toku) means "special" and "観" (kan) relates to "view" or "observation." This term aptly reflects the purpose of the Tokan library, which serves as a specialized tool for observing changes in the Document Object Model (DOM) of web applications.
Tokan is a library designed to simplify and enhance the functionality of the native MutationObserver API. The native API, while powerful, can be complex and cumbersome to use, especially for developers who need to track various types of changes in the DOM. Tokan addresses these challenges by providing a more user-friendly interface that abstracts away some of the complexities associated with the native API.
Key Features:
- Simplified Syntax: The library offers a more intuitive syntax for setting up observers, reducing boilerplate code and making it easier to implement.
- Batch Processing: It can batch multiple mutations together, allowing for more efficient handling of changes and reducing the number of callback executions.
- Custom Callbacks: Users can define custom callback functions that can be triggered based on specific types of mutations, providing greater control over how changes are handled.
Types
TokanMutationFilterCallback
TokanMutationFilter
TokanMutationKindOptions
- Type:
interface - Properties:
oldValue (optional): boolean - Indicates whether the previous value of the node should be recorded.subtree (optional): boolean - Indicates whether the observer should monitor the entire subtree of the target node.filters (optional): TokanMutationFilter[] - An array of filters to apply to nodes being observed.
- Usage Example:
const options: TokanMutationKindOptions = {
oldValue: true,
subtree: true,
filters: ["id", "class", (node) => node.nodeName === "PICTURE"],
};
TokanEventCallback
- Type:
(nodeList: Node, data?: unknown) => void - Description: A callback function that is triggered when a mutation event occurs. It receives the affected node list and optional data related to the mutation.
- Usage Example:
const eventCallback: TokanEventCallback = (nodeList, data) => {
console.log("Mutation detected:", nodeList, data);
};
TokanObserverDescriptor
- Type:
interface - Properties:
id: number - A unique identifier for the observer instance.instance: MutationObserver - The actual MutationObserver instance.config: MutationObserverInit - Configuration options for the MutationObserver.filters: Set<TokanMutationFilterCallback> - A set of filter callbacks applied to nodes.started: boolean - Indicates whether the observer has been started.
- Usage Example:
const observerDescriptor: TokanObserverDescriptor = {
id: 1,
instance: new MutationObserver(eventCallback),
config: { attributes: true },
filters: new Set([filterCallback]),
started: false,
};
Constants
TokanMutationKinds
TokanMutationEvents
Class: Tokan
Static Properties
Tokan.MutationKinds
| Constant | Type | Value | Description |
|---|
| Attr | string | "attributes" | Represents changes to the attributes of elements. |
| CharData | string | "characterData" | Represents changes to the text content of nodes. |
| Nodes | string | "nodes" | Represents additions or removals of child nodes. |
Tokan.MutationEvents
| Constant | Type | Value | Description |
|---|
| Added | string | "added" | Triggered when nodes are added. |
| AttrChanged | string | "attributeChanged" | Triggered when attributes of elements change. |
| CharDataChanged | string | "characterDataChanged" | Triggered when the text content of nodes changes. |
| Removed | string | "removed" | Triggered when nodes are removed. |
Constructor
| Method | Parameters | Description |
|---|
| constructor | target: string | Node | Initializes a new instance of the Tokan class with a target node or a CSS selector string. |
Methods
| Method | Parameters | Returns | Description |
|---|
| observerRouter | mutationList: MutationRecord[], observer: MutationObserver | void | Routes mutation records to the appropriate listeners based on the mutation type and filters. |
| watch | mutationKind: TokanMutationKind, options?: TokanMutationKindOptions | number | undefined | Sets up a new observer for a specific type of mutation. |
| unwatch | id?: number | boolean | Stops and removes an observer or all observers. |
| on | event: TokanMutationEvent, callback: TokanEventCallback | Tokan | Adds an event listener for a specific mutation event. |
| start | id?: number | void | Starts observing with a specific observer or all observers. |
| stop | id?: number | void | Stops observing with a specific observer or all observers. |
Constructor
constructor(target: string | Node)
Private Properties
target: Node
- Description: The target node being observed.
observerId: number
- Description: A unique identifier for observer instances.
observers: Set<TokanObserverDescriptor>
- Description: A set of observer descriptors.
listeners: { [key in TokanMutationEvent]: TokanEventCallback[] }
- Description: An object mapping mutation events to their respective event callbacks.
Methods
observerRouter(mutationList: MutationRecord[], observer: MutationObserver): void
- Description: Routes mutation records to the appropriate listeners based on the mutation type and filters.
- Parameters:
mutationList: MutationRecord[] - A list of mutation records.observer: MutationObserver - The observer instance that generated the mutation records.
- Usage Example: (Internal method, not directly called by users)
watch(mutationKind: TokanMutationKind, options?: TokanMutationKindOptions): number | undefined
- Description: Sets up a new observer for a specific type of mutation.
- Parameters:
mutationKind: TokanMutationKind - The type of mutation to observe.options (optional): TokanMutationKindOptions - Configuration options for the observer.
- Returns:
number | undefined - The ID of the new observer or undefined if an error occurs. - Usage Example:
const observerId = tokan.watch(Tokan.MutationKinds.Attr, {
oldValue: true,
subtree: true,
filters: ['input[type="text"]', filterCallback],
});
unwatch(id?: number): boolean
on(event: TokanMutationEvent, callback: TokanEventCallback): Tokan
start(id?: number): void
stop(id?: number): void
Example Usage
Setting Up an Observer
const tokan = new Tokan("#myElement");
const filterCallback: TokanMutationFilterCallback = (node) =>
node.nodeName === "A";
const observerAttrsId = tokan.watch(Tokan.MutationKinds.Attr, {
oldValue: true,
subtree: true,
filters: ["id", "class", "disabled"],
});
const observerNodesID = tokan.watch(Tokan.MutationKinds.Nodes, {
subtree: true,
filters: [filterCallback],
});
tokan.on(Tokan.MutationEvents.Added, (node) => {
console.log("Node added:", node);
});
tokan.on(Tokan.MutationEvents.AttrChanged, (node, data) => {
console.log("Attribute changed:", node, data);
});
tokan.start();
Stopping an Observer
tokan.stop();
tokan.unwatch();
Listening for Multiple Events
tokan.on(Tokan.MutationEvents.Removed, (node) => {
console.log("Node removed:", node);
});
tokan.on(Tokan.MutationEvents.CharDataChanged, (node, data) => {
console.log("Character data changed:", node, data);
});
tokan.start();