Repository: go-gitea/gitea
File: web_src/js/utils/dom.ts (TypeScript)

Code before:
    for (const el of elems) {
      fn(el);
    }
  }
  return elems;
}

export function queryElemSiblings<T extends Element>(el: Element, selector = '*', fn?: ElementsCallback<T>): ArrayLikeIterable<T> {
  const elems = Array.from(el.parentNode.children) as T[];
  return applyElemsCallback<T>(elems.filter((child: Element) => {
    return child !== el && child.matches(selector);
  }), fn);
}

// it works like jQuery.children: only the direct children are selected
export function queryElemChildren<T extends Element>(parent: Element | ParentNode, selector = '*', fn?: ElementsCallback<T>): ArrayLikeIterable<T> {
  if (isInFrontendUnitTest()) {
    // https://github.com/capricorn86/happy-dom/issues/1620 : ":scope" doesn't work
    const selected = Array.from<T>(parent.children as any).filter((child) => child.matches(selector));
    return applyElemsCallback<T>(selected, fn);
  }
  return applyElemsCallback<T>(parent.querySelectorAll(`:scope > ${selector}`), fn);
}

// it works like parent.querySelectorAll: all descendants are selected
// in the future, all "queryElems(document, ...)" should be refactored to use a more specific parent
export function queryElems<T extends HTMLElement>(parent: Element | ParentNode, selector: string, fn?: ElementsCallback<T>): ArrayLikeIterable<T> {
  return parent ? applyElemsCallback<T>(parent.querySelectorAll(selector), fn) : [];
}

export function onDomReady(cb: () => Promisable<void>) {
  if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', cb);
  } else {
    cb();
  }
}

// checks whether an element is owned by the current document, and whether it is a document fragment or element node
// if it is, it means it is a "normal" element managed by us, which can be modified safely.
export function isDocumentFragmentOrElementNode(el: Node) {
  try {
    return el.ownerDocument === document && el.nodeType === Node.ELEMENT_NODE || el.nodeType === Node.DOCUMENT_FRAGMENT_NODE;
  } catch {
    // in case the el is not in the same origin, then the access to nodeType would fail
    return false;
  }
}

// autosize a textarea to fit content. Based on
// https://github.com/github/textarea-autosize

Review comment (refactor):
```suggestion
// in the future, all "queryElems(document, ...)" should be refactored to use a more specific parent if the targets are not for page-level components.
```

Code after:
    for (const el of elems) {
      fn(el);
    }
  }
  return elems;
}

export function queryElemSiblings<T extends Element>(el: Element, selector = '*', fn?: ElementsCallback<T>): ArrayLikeIterable<T> {
  const elems = Array.from(el.parentNode.children) as T[];
  return applyElemsCallback<T>(elems.filter((child: Element) => {
    return child !== el && child.matches(selector);
  }), fn);
}

// it works like jQuery.children: only the direct children are selected
export function queryElemChildren<T extends Element>(parent: Element | ParentNode, selector = '*', fn?: ElementsCallback<T>): ArrayLikeIterable<T> {
  if (isInFrontendUnitTest()) {
    // https://github.com/capricorn86/happy-dom/issues/1620 : ":scope" doesn't work
    const selected = Array.from<T>(parent.children as any).filter((child) => child.matches(selector));
    return applyElemsCallback<T>(selected, fn);
  }
  return applyElemsCallback<T>(parent.querySelectorAll(`:scope > ${selector}`), fn);
}

// it works like parent.querySelectorAll: all descendants are selected
// in the future, all "queryElems(document, ...)" should be refactored to use a more specific parent if the targets are not for page-level components.
export function queryElems<T extends HTMLElement>(parent: Element | ParentNode, selector: string, fn?: ElementsCallback<T>): ArrayLikeIterable<T> {
  return applyElemsCallback<T>(parent.querySelectorAll(selector), fn);
}

export function onDomReady(cb: () => Promisable<void>) {
  if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', cb);
  } else {
    cb();
  }
}

// checks whether an element is owned by the current document, and whether it is a document fragment or element node
// if it is, it means it is a "normal" element managed by us, which can be modified safely.
export function isDocumentFragmentOrElementNode(el: Node) {
  try {
    return el.ownerDocument === document && el.nodeType === Node.ELEMENT_NODE || el.nodeType === Node.DOCUMENT_FRAGMENT_NODE;
  } catch {
    // in case the el is not in the same origin, then the access to nodeType would fail
    return false;
  }
}

// autosize a textarea to fit content. Based on
// https://github.com/github/textarea-autosize