Xây dựng Trình soạn thảo văn bản trực tuyến đơn giản bằng JavaScript

Hướng dẫn này sẽ chỉ cho bạn cách xây dựng một trình soạn thảo văn bản trực tuyến đơn giản bằng HTML, CSS và JavaScript. Bạn sẽ tìm hiểu cách tạo đánh dấu và kiểu của trình soạn thảo, đồng thời bạn sẽ thấy cách sử dụng JavaScript để thêm chức năng, chẳng hạn như chỉnh sửa văn bản và hoàn tác/làm lại. Đến cuối hướng dẫn này, bạn sẽ có thể xây dựng một trình soạn thảo văn bản trực tuyến đơn giản mà bạn có thể sử dụng để tạo và chỉnh sửa tài liệu văn bản.

Để xây dựng trình soạn thảo văn bản trực tuyến đơn giản bằng HTML, CSS và JavaScript, bạn cần tạo ba tệp: tệp HTML, CSS & JavaScript. Khi bạn tạo các tệp này, chỉ cần dán các mã đã cho vào tệp của bạn.

Mã nguồn đầy đủ:

Tệp HTML

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.2.1/css/all.min.css">
    <link rel="stylesheet" href="style.css">
    <title>#2 - Online Text Editor | AsmrProg</title>
</head>

<body>

    <div class="container">
        <div class="options">
            <button id="bold" class="option-button format">
                <i class="fa-solid fa-bold"></i>
            </button>
            <button id="superscript" class="option-button script">
                <i class="fa-solid fa-superscript"></i>
            </button>
            <button id="subscript" class="option-button script">
                <i class="fa-solid fa-subscript"></i>
            </button>

            <button id="insertOrderedList" class="option-button">
                <div class="fa-solid fa-list-ol"></div>
            </button>
            <button id="insertUnorderedList" class="option-button">
                <i class="fa-solid fa-list"></i>
            </button>

            <button id="undo" class="option-button">
                <i class="fa-solid fa-rotate-left"></i>
            </button>
            <button id="redo" class="option-button">
                <i class="fa-solid fa-rotate-right"></i>
            </button>

            <button id="createLink" class="adv-option-button">
                <i class="fa fa-link"></i>
            </button>
            <button id="unlink" class="option-button">
                <i class="fa fa-unlink"></i>
            </button>

            <button id="justifyLeft" class="option-button align">
                <i class="fa-solid fa-align-left"></i>
            </button>
            <button id="justifyCenter" class="option-button align">
                <i class="fa-solid fa-align-center"></i>
            </button>
            <button id="justifyRight" class="option-button align">
                <i class="fa-solid fa-align-right"></i>
            </button>
            <button id="justifyFull" class="option-button align">
                <i class="fa-solid fa-align-justify"></i>
            </button>
            <button id="indent" class="option-button spacing">
                <i class="fa-solid fa-indent"></i>
            </button>
            <button id="outdent" class="option-button spacing">
                <i class="fa-solid fa-outdent"></i>
            </button>
            <select id="formatBlock" class="adv-option-button">
                <option value="H1">H1</option>
                <option value="H2">H2</option>
                <option value="H3">H3</option>
                <option value="H4">H4</option>
                <option value="H5">H5</option>
                <option value="H6">H6</option>
            </select>
            <select id="fontName" class="adv-option-button"></select>
            <select id="fontSize" class="adv-option-button"></select>

            <div class="input-wrapper">
                <input type="color" id="foreColor" class="adv-option-button">
                <label for="foreColor">Font Color</label>
            </div>
            <div class="input-wrapper">
                <input type="color" id="backColor" class="adv-option-button">
                <label for="backColor">Highlight Color</label>
            </div>

        </div>
        <div id="text-input" contenteditable="true"></div>
    </div>

    <script src="script.js"></script>


</body>

</html>

Tệp CSS:

@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700&display=swap');

*{
    padding: 0;
    margin: 0;
    box-sizing: border-box;
}

body{
    background-color: #338cf4;
}

.container{
    background-color: #fff;
    width: 90vmin;
    padding: 50px 30px;
    position: absolute;
    transform: translate(-50%, -50%);
    left: 50%;
    top: 50%;
    border-radius: 10px;
    box-shadow: 0 25px 50px rgba(7, 20, 35, 0.2);
}

.options{
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 15px;
}

button{
    width: 28px;
    height: 28px;
    display: grid;
    place-items: center;
    border-radius: 3px;
    border: none;
    background-color: #fff;
    outline: none;
    color: #020929;
    cursor: pointer;
}

select{
    padding: 7px;
    border: 1px solid #020929;
    border-radius: 3px;
    cursor: pointer;
}

.options label,
.options select{
    font-family: 'Poppins', sans-serif;
}

input[type="color"]{
    -webkit-appearance: none;
    -moz-appearance: none;
    appearance: none;
    background-color: transparent;
    width: 40px;
    height: 28px;
    border: none;
    cursor: pointer;
}

input[type="color"]::-webkit-color-swatch{
    border-radius: 15px;
    box-shadow: 0 0 0 2px #fff, 0 0 0 3px #020929;
}

input[type="color"]::-moz-color-swatch{
    border-radius: 15px;
    box-shadow: 0 0 0 2px #fff, 0 0 0 3px #020929;
}

#text-input{
    margin-top: 10px;
    border: 1px solid #ddd;
    padding: 20px;
    height: 50vh;
}

.active{
    background-color: #e0e9ff;
}

Tệp JavaScript:

let optionsButtons = document.querySelectorAll(".option-button");
let advancedOptionButton = document.querySelectorAll(".adv-option-button");
let fontName = document.getElementById("fontName");
let fontSizeRef = document.getElementById("fontSize");
let writingArea = document.getElementById("text-input");
let linkButton = document.getElementById("createLink");
let alignButtons = document.querySelectorAll(".align");
let spacingButtons = document.querySelectorAll(".spacing");
let formatButtons = document.querySelectorAll(".format");
let scriptButtons = document.querySelectorAll(".script");

let fontList = [
    "Arial",
    "Verdana",
    "Times New Roman",
    "Garamond",
    "Georgia",
    "Courier New",
    "Cursive",
];

const intializer = () => {
    highlighter(alignButtons, true);
    highlighter(spacingButtons, true);
    highlighter(formatButtons, false);
    highlighter(scriptButtons, true);

    fontList.map((value) => {
        let option = document.createElement("option");
        option.value = value;
        option.innerHTML = value;
        fontName.appendChild(option);
    });

    for (let i = 1; i <= 7; i++) {
        let option = document.createElement("option");
        option.value = i;
        option.innerHTML = i;
        fontSizeRef.appendChild(option);
    }

    fontSizeRef.value = 3;
};

const modifyText = (command, defaultUi, value) => {
    document.execCommand(command, defaultUi, value);
};

optionsButtons.forEach((button) => {
    button.addEventListener("click", () => {
        modifyText(button.id, false, null);
    });
});

advancedOptionButton.forEach((button) => {
    button.addEventListener("change", () => {
        modifyText(button.id, false, button.value);
    });
});

linkButton.addEventListener("click", () => {
    let userLink = prompt("Enter a URL?");
    if (/http/i.test(userLink)) {
        modifyText(linkButton.id, false, userLink);
    } else {
        userLink = "http://" + userLink;
        modifyText(linkButton.id, false, userLink);
    }
});

const highlighter = (className, needsRemoval) => {
    className.forEach((button) => {
        button.addEventListener("click", () => {
            if (needsRemoval) {
                let alreadyActive = false;
                if (button.classList.contains("active")) {
                    alreadyActive = true;
                }
                highlighterRemover(className);
                if (!alreadyActive) {
                    button.classList.add("active");
                }
            } else {
                button.classList.toggle("active");
            }
        });
    });
};

const highlighterRemover = (className) => {
    className.forEach((button) => {
        button.classList.remove("active");
    });
};

window.onload = intializer();

Hướng dẫn này cung cấp các bước và mã đơn giản để giúp bạn xây dựng trình soạn thảo văn bản trực tuyến đơn giản bằng cách sử dụng HTML, CSS và JavaScript.

1.30 GEEK