DEV Community

Harsh Singh
Harsh Singh

Posted on

Functional DOM Manipulation

Functional DOM Manipulation

Build A Functional DOM Manipulation Toolkit and a Todo App Demo with it.

The Toolkit

const SVG_NS = 'http://www.w3.org/2000/svg';

export const el = type => document.createElement(type);

export const svg = type => document.createElementNS(SVG_NS, type);

export const text = value => document.createTextNode(value);

export const append = (parent, children) => {
  const fragment = document.createDocumentFragment();
  fragment.append(...children);
  parent.appendChild(fragment);
};

export const appendChild = (parent, child) =>
  parent.appendChild(child);

export const attr = (node, name, value) => {
  if(!value) {
    node.removeAttribute(value);
    return;
  }

  node.setAttribute(name, value);
};

export const addClass = (node, ...classNames) =>
  node.classList.add(...classNames);

export const setTextContent = (node, text) => 
  node.textContent = text;

export const on = (node, type, handler) =>
  node.addEventListener(type, handler);

export const off = (node, type, handler) =>
  node.removeEventListener(type, handler);
Enter fullscreen mode Exit fullscreen mode

TODO APP DEMO

import { el, on, off, setTextContent, text, attr, addClass, append, appendChild } from './tookit.js';

const createDeleteTodoBtn = handleTodoDelete => {
  const deleteTodoBtn = el('button');
  setTextContent(deleteTodoBtn, 'Delete Todo');

  const handleDelete = () => {
    off(deleteTodoBtn, 'click', handleDelete);
    handleTodoDelete();
  };

  on(deleteTodoBtn, 'click', handleDelete);

  return deleteTodoBtn;
};

const createTodo = ({ todo, id }) => {
  const todoItem = el('li');
  const todoText = text(todo);

  const handleDelete = () => {
    todoItem.remove();
    // do cleanup stuff
  };

  const deleteTodoBtn = createDeleteTodoBtn(handleDelete);

  addClass(todoItem, 'todo');

  attr(todoItem, 'data-id', id);

  append(todoItem, [todoText, deleteTodoBtn]);

  return todoItem;
};

const createTodoList = data => {
  const todoList = el('ul');

  addClass(todoList, 'todo-list');

  const todos = data.map(createTodo);

  append(todoList, todos);

  return todoList;
};

const createTodoForm = handleForm => {
  const todoForm = el('div');
  addClass(todoForm, 'todo-form');
  const todoInput = el('input');
  const handleSubmit = e => {
    e.preventDefault();
    const todo = todoInput.value;
    if(!todo) {
      return;
    }
    handleForm({
      todo,
      id: crypto.randomUUID();
    });
  };
  on(todoForm, 'submit', handleSubmit);

  return todoForm;
};

const createTodoApp = initialData => {
  const appContainer = el('div');

  addClass(appContainer, 'todo-app');

  const todoList = createTodoList(initialData);

  const handleFormSubmit = todo => {
    appendChild(todoList, createTodo(todo));
  };

  const todoForm = createTodoForm(handleFormSubmit);

  append(appContainer, [todoForm, todoList]);

  return appContainer;
};
Enter fullscreen mode Exit fullscreen mode

Top comments (0)