CotomyElement in Practice

A practical guide to CotomyElement usage in real business screens with concrete DOM handling patterns.

The focus here is implementation. In real business screens, CotomyElement helps keep DOM handling consistent across tables, forms, buttons, and scroll-driven UI.

CotomyElement Retrieval in Real Screens

byId, first, last, find, contains, containsById, and empty are the static entry points you use first in view.ts. In practice, you combine them to build one screen setup flow: find root, detect optional blocks, then apply bulk operations.

Example: admin list screen with row actions and bulk controls.

import { CotomyElement } from "cotomy";

const table = CotomyElement.byId("user-table");
if (!table) return;

const toolbar = CotomyElement.byId("user-toolbar") ?? CotomyElement.empty();
const saveButton = CotomyElement.first("#save-users");
const latestRow = CotomyElement.last(".user-row");
const rows = CotomyElement.find(".user-row");
const hasPager = CotomyElement.contains("[data-role='pager']");
const hasBulkAction = CotomyElement.containsById("bulk-actions");

if (!hasPager) {
  toolbar.attribute("data-layout", "single");
}
if (!hasBulkAction) {
  toolbar.attribute("data-mode", "simple");
}

saveButton?.attribute("data-state", rows.length > 0 ? "ready" : "disabled");
latestRow?.scrollIn();

What this buys you:

byId gives stable page contracts, first and last fit single-target operations, find works for batch control, contains works as a cheap guard before heavier setup, and empty gives a safe fallback boundary.

Child Retrieval Variations

You usually combine screen root + child selection. This keeps operations scoped and predictable.

const form = CotomyElement.byId("order-form");
if (!form) return;

// selector-based child retrieval
const requiredFields = form.find("[data-required='true']");

// data-attribute filtered retrieval
const warningFields = form.find("[data-state='warning']");

requiredFields.forEach(field => field.addClass("required-highlight"));
warningFields.forEach(field => field.attribute("data-visible", "true"));

Common cases:

you can apply classes to all child nodes that match a condition, enable only elements with data-state=‘editable’, and keep one form isolated even when the page has multiple forms.

Loop Patterns with find().forEach()

Batch operations are where CotomyElement becomes practical in day-to-day work.

const table = CotomyElement.byId("invoice-table");
if (!table) return;

// highlight only checked rows
table.find("tr[data-checked='true']").forEach(row => {
  row.addClass("is-selected");
});

// toggle disabled in bulk
const lock = true;
table.find("input, select, button").forEach(el => {
  el.attribute("disabled", lock ? "true" : null);
});

// emphasize error fields
table.find("[data-error='true']").forEach(field => {
  field.addClass("has-error");
  field.attribute("aria-invalid", "true");
});

Parent and Ancestor Retrieval with closest()

closest() is useful when events happen deep in a row or modal.

const deleteButtons = CotomyElement.find("[data-action='delete-row']");
deleteButtons.forEach(btn => {
  btn.click(() => {
    const row = btn.closest("[data-row-id]");
    if (!row) return;
    row.remove();
  });
});

const modalSubmit = CotomyElement.first("#modal-save");
modalSubmit?.click(() => {
  const form = modalSubmit.closest("form");
  form?.trigger("submit");
});

Typical operations:

you find a row container from an inline action button, find a form root from a modal footer button, and keep event handlers small without global selector re-query.

Size and Scroll Metrics for Layout Control

Use size values for behavior, not for static styling. In operational screens, this is common for sticky headers and dynamic panels.

import { CotomyWindow } from "cotomy";

const header = CotomyElement.byId("page-header");
const body = CotomyElement.byId("content-scroll");
const summary = CotomyElement.byId("summary-panel");
if (!header || !body || !summary) return;

const win = CotomyWindow.instance;
const headerHeight = header.outerHeight;
const viewportHeight = body.height;
const panelWidth = summary.width;
const panelOuterWidth = summary.outerWidth;
const y = body.scrollTop;
const x = win.scrollLeft;
const top = summary.absolutePosition.top;
const left = summary.absolutePosition.left;

// dynamic height under fixed header
body.style("height", "calc(100vh - " + headerHeight + "px)");

// sync floating summary position with current scroll/offset
summary.style("top", Math.max(y + 8, top) + "px");
summary.style("left", Math.max(x + 12, left) + "px");
summary.attribute("data-width", panelWidth + "/" + panelOuterWidth);
summary.attribute("data-viewport-height", String(viewportHeight));

Metrics to check in one place:

width and height, outerWidth and outerHeight, offset-like values such as position/absolutePosition/rect, and scrollTop on elements with scrollLeft on CotomyWindow.

Visibility and Operability Checks

Before applying bulk changes, check whether the target is active in the current screen state.

const tabs = CotomyElement.find("[data-tab-panel]");

tabs.forEach(panel => {
  const measurable = panel.width > 0 && panel.height > 0;
  const active = panel.visible && panel.enabled && panel.attached && measurable;
  if (!active) return;

  panel.find("input, select, textarea").forEach(input => {
    input.attribute("data-checked-at", Date.now().toString());
  });
});

This pattern avoids touching hidden tab content or detached nodes during tab switching and partial updates.

inview / outview for Infinite Scroll

inview() and outview() are practical for SPA-like paging surfaces. Typical pattern: watch a sentinel row at the bottom and load next data chunk.

import { CotomyElement } from "cotomy";

const list = CotomyElement.byId("activity-list");
const sentinel = CotomyElement.byId("pager-sentinel");
let loading = false;
let page = 1;

async function loadNext(): Promise<void> {
  if (!list || loading) return;
  loading = true;
  try {
    const res = await fetch("/api/activity?page=" + (page + 1));
    const html = await res.text();
    list.append(new CotomyElement(html));
    page += 1;
  } finally {
    loading = false;
  }
}

sentinel?.inview(async () => {
  await loadNext();
});

sentinel?.outview(() => {
  // can be used for telemetry or cancel logic
});
sequenceDiagram
  participant User
  participant Window
  participant IO as IntersectionObserver
  participant CE as CotomyElement
  participant Page as Page Logic

  User->>Window: scroll
  Window->>IO: detect intersection
  IO->>CE: inview event
  CE->>Page: load next page

DOM Boundary Map

flowchart TD
  DOM[Real DOM]
  CE[CotomyElement]
  Page[Page Controller]

  CE --> DOM
  Page --> CE

Wrap-up

CotomyElement is most effective when you keep a single handling style for lookup, traversal, state checks, and batch updates. That consistency is what keeps operational screens readable as they grow.

Next article: CotomyElement Value and Form Behavior

If you need design background, read CotomyElement Boundary . If you need first-step basics, read Working with CotomyElement .

Usage Series

This article is part of the Cotomy Usage Series, which focuses on concrete runtime behavior and day-to-day API usage.

Series articles: CotomyElement in Practice, CotomyElement Value and Form Behavior , CotomyApi in Practice , and Debugging Features and Runtime Inspection in Cotomy .

Links

Previous: Page Lifecycle Coordination .
Related: Working with CotomyElement .

Learn Cotomy

Cotomy is a DOM-first UI runtime for long-lived business applications.