badeball/xpath-react

View on GitHub
lib/types/react_element.js

Summary

Maintainability
B
4 hrs
Test Coverage
import { DOCUMENT_NODE, ELEMENT_NODE, TEXT_NODE } from "xpath-evaluator";

import ReactAttribute from "./react_attribute";

import wrapNativeElements from "./wrap_native_elements";

import compareDocumentPosition from "./compare_document_position";

export default class ReactElement {
  constructor(nativeNode, parent, nChild) {
    this.nativeNode = nativeNode;
    this.parent = parent;
    this.nChild = nChild;
  }

  getId() {
    return this.getParent().getId() + "." + this.nChild;
  }

  isEqual(node) {
    return this.getId() === node.getId();
  }

  getNativeNode() {
    return this.nativeNode;
  }

  asString() {
    let textContent = "";

    this.getChildNodes().forEach(function (child) {
      if (child.getNodeType() === ELEMENT_NODE ||
          child.getNodeType() === TEXT_NODE) {
        textContent = textContent + child.asString();
      }
    });

    return textContent;
  }

  asNumber() {
    return +this.asString();
  }

  getNodeType() {
    return ELEMENT_NODE;
  }

  getParent() {
    return this.parent;
  }

  getChildNodes() {
    if (!this.nativeNode.props || !this.nativeNode.props.children) {
      return [];
    }

    return wrapNativeElements(this, this.nativeNode.props.children);
  }

  getFollowingSiblings() {
    const followingSiblings = [];

    const siblings = this.getParent().getChildNodes();

    const thisSiblingIndex = siblings.findIndex((sibling) => {
      return sibling.isEqual(this);
    });

    for (let i = thisSiblingIndex + 1; i < siblings.length; i++) {
      followingSiblings.push(siblings[i]);
    }

    return followingSiblings;
  }

  getPrecedingSiblings() {
    const precedingSiblings = [];

    const siblings = this.getParent().getChildNodes();

    const thisSiblingIndex = siblings.findIndex((sibling) => {
      return sibling.isEqual(this);
    });

    for (let i = 0; i < thisSiblingIndex; i++) {
      precedingSiblings.push(siblings[i]);
    }

    return precedingSiblings;
  }

  getName() {
    if (typeof this.nativeNode.type === "string") {
      return this.nativeNode.type;
    } else if (typeof this.nativeNode.type === "function") {
      return this.nativeNode.type.displayName || this.nativeNode.type.name;
    }
  }

  getAttributes() {
    if (!this.nativeNode.props) {
      return [];
    }

    const attributes = [];

    let i = 0;

    for (let attribute in this.nativeNode.props) {
      if (attribute !== "children") {
        attributes.push(new ReactAttribute(attribute, this.nativeNode.props[attribute], this, i++));
      }
    }

    return attributes;
  }

  getOwnerDocument() {
    if (this.getParent().getNodeType() === DOCUMENT_NODE) {
      return this.getParent();
    } else {
      return this.getParent().getOwnerDocument();
    }
  }

  /* eslint-disable no-underscore-dangle */
  _getElementById(id) {
    if (this.nativeNode.props && this.nativeNode.props.id === id) {
      return this;
    } else {
      const children = this.getChildNodes();

      for (let child of children) {
        if (child.getNodeType() === ELEMENT_NODE) {
          const elementWithId = child._getElementById(id);

          if (elementWithId) {
            return elementWithId;
          }
        }
      }
    }
  }
  /* eslint-enable no-underscore-dangle */

  toString() {
    let name = this.getName();

    if (this.nativeNode.props) {
      if (this.nativeNode.props.className) {
        name = name + "." + this.nativeNode.props.className.split(/\s+/g).join(".");
      }

      if (this.nativeNode.props.id) {
        name = name + "#" + this.nativeNode.props.id;
      }
    }

    return "Node<" + name + ">";
  }

  compareDocumentPosition(other) {
    return compareDocumentPosition(this, other);
  }
}