npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@laserware/dominator

v5.4.2

Published

Better ergonomics for working with the DOM and TypeScript.

Downloads

139

Readme

Dominator

Better ergonomics for working with the DOM and TypeScript.

See documentation if you want to get right to the API. For a high-level overview of the library, keep reading!

Examples

Let's face it, working with the DOM API kind of sucks (especially with TypeScript). This library aims to make it a little less painful.

The following examples compare the use of DOM APIs with this library.

Creating Elements

Instead of creating an Element with the DOM APIs:

const div = document.createElement("div");
div.id = "example";
div.ariaLabel = "Hello!";

You can use the createElement function:

import { createElement } from "@laserware/dominator";

const div = createElement("div", { id: "example", ariaLabel: "Hello!" });

Finding Elements

Finding a single element or multiple elements in the DOM isn't that bad.

Assuming you have this HTML:

<div role="grid" aria-colcount="6">
  <div role="rowgroup">
    <div role="row">
      <div role="columnheader" aria-colindex="1">First name</div>
      <div role="columnheader" aria-colindex="2">Last name</div>
      <div role="columnheader" aria-colindex="5">City</div>
      <div role="columnheader" aria-colindex="6">Zip</div>
    </div>
  </div>
  <div role="rowgroup">
    <div role="row">
      <div role="gridcell" aria-colindex="1">Debra</div>
      <div role="gridcell" aria-colindex="2">Burks</div>
      <div role="gridcell" aria-colindex="5">New York</div>
      <div role="gridcell" aria-colindex="6">14127</div>
    </div>
  </div>
  …
</div>

Here's a couple of ways you could find element(s) using the DOM APIs:

// Single element:
const firstHeaderRow = document.querySelector(`[role="row"] [role="columnheader"]:first-child`);

// Multiple elements in document:
const allGridCells = document.querySelectorAll(`[role="gridcell"]`);

// Finding all children in parent element:
const grid = document.querySelector("grid");
const gridRows = grid.querySelectorAll(`[role="row"]`);

But there are some issues. For one, document.querySelectorAll returns a NodeList, which are annoying to work with.

You can use findElement and findAllElements instead:

import { findElement, findAllElements } from "@laserware/dominator";

const firstHeaderColumn = findElement(
  `[role="row"] [role="columnheader"]:first-child`,
);

// Returns the grid cell elements as an array:
const allGridCells = findAllElements<"div">(`[role="gridcell"]`);

// You can use string selectors for the target and parent to get children:
const gridRows = findAllElements(`[role="row"]`, "grid");

Setting Attributes

Setting attributes with the DOM APIs has some drawbacks:

  1. You need to call setAttribute for each attribute you want to set.
  2. You have to stringify each value before setting it.
const div = document.createElement("div");

div.setAttribute("role", "gridcell");

// Need to convert boolean to a string:
div.setAttribute("aria-disabled", "true");

// And do the same for numbers:
div.setAttribute("aria-colindex", "1");

You can use setAttribute or setAttributes instead. Both functions return the element:

import { 
  createElement,
  setAttribute,
  setAttributes, 
} from "@laserware/dominator";

let div = createElement("div");

// Set one attribute:
div = setAttribute(div, "role", "gridcell");

// Set multiple attributes:
div = setAttributes(div, {
  // You can just use a boolean, no need to stringify:
  "aria-disabled": true,
  // Same goes for numbers:
  "aria-colindex": 1,
});

Removing Attributes

Removing attributes using the DOM APIs requires that you remove each attribute individually.

Assuming you have this HTML:

<div id="example" role="gridcell" aria-disabled="true">Example</div>

Instead of using the element.removeAttribute API:

const div = document.getElementById("example");

div.removeAttribute("role");
div.removeAttribute("aria-disabled");

You can use removeAttribute or removeAttributes. Both functions return the element:

import {
  findElement,
  removeAttribute,
  removeAttributes,
} from "@laserware/dominator";

let div = findElement("#example")!;

div = removeAttribute(div, "role");

div = removeAttributes(div, ["aria-disabled", "aria-colindex"]);

Checking for Attributes

If you want to check for the existence of attributes using the DOM API, you'd use element.hasAttribute.

If you want to check if a value matches, you're stuck with the annoyances of getAttribute. So you're back to dealing with strings.

Assuming you have this HTML:

<div id="example" role="gridcell" aria-disabled="true" aria-colindex="1">Example</div>

Here's how you would check for attributes with the DOM APIs:

const div = document.getElementById("example");

const hasRole = div.hasAttribute("role");

const index = 1;
const isCol = div.getAttribute("aria-colindex") === index.toString();

You can use hasAttribute, hasAllAttributes, and hasSomeAttributes instead:

import { 
  findElement,
  hasAttribute,
  hasAllAttributes,
  hasSomeAttributes,
} from "@laserware/dominator";

const div = findElement("#example");

const hasRole = hasAttribute(div, "role");

// Check if any of the attributes are present:
const someArePresent = hasSomeAttributes(div, ["aria-colindex"]);

// Check if any of the attributes names and values match:
const someMatchValues = hasSomeAttributes(div, { "aria-colindex": 1 });

// Check if all of the attributes match, you can use `null` to
// check for the _existence_ of an attribute only:
const allMatch = hasAllAttributes(div, { 
  "aria-colindex": 1, 
  "aria-disabled": null,
});

Selecting Elements with Attributes

Building a CSS selector to find something based on attributes requires a lot of manual labor.

Assuming you have this HTML:

<div role="grid" aria-colcount="6">
  <div role="rowgroup">
    <div role="row">
      <div role="columnheader" aria-colindex="1">First name</div>
      <div role="columnheader" aria-colindex="2">Last name</div>
      <div role="columnheader" aria-colindex="5">City</div>
      <div role="columnheader" aria-colindex="6">Zip</div>
    </div>
  </div>
  <div role="rowgroup">
    <div role="row">
      <div role="gridcell" aria-colindex="1">Debra</div>
      <div role="gridcell" aria-colindex="2">Burks</div>
      <div role="gridcell" aria-colindex="5">New York</div>
      <div role="gridcell" aria-colindex="6">14127</div>
    </div>
  </div>
  …
</div>

You'll need to write the selectors yourself:

const firstHeaderColumn = findElement(`[role="row"] [role="columnheader"]`);

const secondGridCell = findElement(`[role="gridcell"][aria-colindex="2"]`);

You can use selectAttribute and selectAttributes instead:

import { 
  findElement,
  selectAttribute,
  selectAttributes,
} from "@laserware/dominator";

const firstHeaderSelector = [
  selectAttribute("role", "row"),
  selectAttribute("role", "columnheader"),
].join(" ");

const firstHeaderColumn = findElement(firstHeaderSelector);

const secondGridCellSelector = selectAttributes({
  role: "gridcell",
  // Note that we're using a number:
  "aria-colindex": 2,
});

const secondGridCell = findElement(secondGridCellSelector);

You can do more than work with attributes. You can also set, get, remove, and select dataset entries, CSS variables, and styles.