javascriptes6-modules

How do I break down my code into smaller and manageable chunks of modules?


I am learning JavaScript and I currently I am learning about modules. I have no idea how to do it. I do know that I have to use export and import to do it but I don't know how I should proceed with it and how to make separate files for each module.

function select() {
    const add = document.querySelector(".add-btn");
    add.addEventListener("click", addItem);
}

function addItem() {
    const main = document.querySelector(".main");

    const newItem = document.createElement("div");
    const newHeading = document.createElement("h2");
    const deleteButton = document.createElement("button");
    const inputArea = document.createElement("input");

    newItem.classList.add("new-div");
    newHeading.classList.add("new-heading");
    deleteButton.classList.add("delete-btn");
    inputArea.classList.add("textbox");

    deleteButton.innerText = "Delete";
    inputArea.type = "text";
    inputArea.placeholder = "Enter here...";

    num = main.children.length;
    newHeading.innerText = `Task ${num}`;

    newItem.append(newHeading, deleteButton, inputArea);

    inputArea.addEventListener("keydown", ({ key }) => {
        if (key == "Enter" && inputArea.value.trim() != "") {
            const textValue = inputArea.value;

            const displayText = document.createElement("p");

            displayText.classList.add("txt-val");
            displayText.innerText = textValue;

            newItem.appendChild(displayText);
            newItem.removeChild(inputArea);
        }
    })

    document.querySelector(".main").appendChild(newItem);

    inputArea.focus();  /* this makes the text box appear with a blinking cursor by default */          

    deleteItem(deleteButton, newItem);

    num++;
}

function deleteItem(button, item) {
    button.addEventListener("click", () => {
        const main = document.querySelector(".main");
        main.removeChild(item);
    });
}

select();
*,
::before,
::after {
    box-sizing: border-box;
    margin: 0;
    padding: 0;
}

h1 {
    text-align: center;
    margin-top: 2em;
    text-decoration: underline;
    font-size: 3em;
}

.main {
    margin-top: 3em;
    border-right: 12px solid rgb(108, 179, 202);
    border-left: 12px solid rgb(108, 179, 202);
    border-top: 8px solid rgb(108, 179, 202);
    border-bottom: 8px solid rgb(108, 179, 202);
    height: 100%;
    position: relative;
}

.add-btn {
    background-color: rgb(74, 184, 74);
    color: white;
    font-weight: bolder;
    font-size: x-large;
    padding: 10px;
    border: none;
    border-radius: 10px;
    cursor: pointer;
    height: 2em;
    position: absolute;
    translate: -2.5em -1.1em;
    z-index: 1000;
}

.add-btn:hover {
    background-color: rgb(112, 219, 112);
    transition: 0.5s;
}

.main-button-class {
    text-align: center;
}

.new-heading {
    font-family: Georgia, 'Times New Roman', Times, serif;
}

.new-div {
    position: relative;
    border: 5px solid rgb(84, 153, 218);
    margin-top: 65px;
    margin-bottom: 30px;
    margin-left: 32px;
    margin-right: 32px;
    padding: 15px;
    height: 170px;
    text-align: center;

}

.delete-btn {
    width: 65px;
    height: 50px;
    background-color: red;
    color: white;
    font-weight: bold;
    font-size: large;
    border-radius: 10px;
    position: absolute;
    top: 0;
    right: 0;
    translate: 25px -25px;
    cursor: pointer;
    border: none;
}

.textbox {
    width: 95%;
    height: 80px;
    margin-top: 15px;
    padding: 15px;
    border: 1px solid black;
}

.txt-val {
    font-size: x-large;
    color: black;
    margin-top: 35px;
}

.delete-btn:hover {
    background-color: rgb(255, 105, 105);
    transition: 0.5s;
}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Todo List New</title>
    <script defer src="/JavaScript/Todo List New.js"></script>
    <link rel="stylesheet" href="/CSS/Todo List New.css">
</head>
<body>
    <h1>Todo List</h1>
    
    <div class="main">
        <div class="main-button-class">
            <button type="button" class="add-btn">Add Task</button>
        </div>
    </div>
</body>
</html>

I have posted my code above. But I don't know how to break down my JavaScript files into smaller chunks and how to bring them all together. I am also hesitant to do it because when I tried it on my own, the code didn't work and the control flow got messed up.


Solution

  • I cleaned up some eventListeners and delegated them from the main div

    Here is a working demo : https://plungjan.name/SO/jsmodules/

    I made this folder structure

    📁 Project Root
    ├─ index.html
    ├─ css/
    │  └─ main.css
    └─ js/
       ├─ main.js
       ├─ domUtils.js
       └─ selectHandler.js
    

    index.html has

    <script type="module" defer src="js/main.js"></script>
    <link rel="stylesheet" href="css/main.css" />
    

    main.js has

    import { initHandlers } from './selectHandler.js';
    initHandlers();
    

    selectHandler.js has

    import { createNewItem } from './domUtils.js';
    
    export function initHandlers() {
      const main = document.querySelector('.main');
      const addBtn = document.querySelector('.add-btn');
      addBtn.addEventListener('click', () => {
        const newItem = createNewItem();
        main.appendChild(newItem);
        newItem.querySelector('.textbox').focus();
      });
      main.addEventListener('submit', (event) => { // delegation 
        event.preventDefault();
        ...
      });
      main.addEventListener('click', (event) => { // delegation
        if (event.target.classList.contains('delete-btn')) {
          const item = event.target.closest('.new-div');
          item.remove();
        }
      });
    } 
    

    and domUtils.js has

    export function createNewItem() {
      const newItem = document.createElement('div');
      ...
      return newItem;
    }