Rich text editor using HTML CSS and JavaScript with words counter

This project will be the most memorablt in your web development career. Because you will learn to create a rich text editor with a dark theme. Also, I am sharing the source code here. If you like the project, don't forget to share it with your friends. 

Create a rich text editor using HTML CSS and JavaScript with words counter

What is a rich text editor?

The rich text editor is the simplified name of the WYSIWYG HTML editor. It is the tool that allows the user to write, edit and process the text. The main aim of the WYSIWYG HTML editor(rich text editor) is to simplify the task of coding while processing tests. The important features such as bold, italic, underline, headings, linking, etc... Is possible in this tool. There are a lot of components that can be added to it according to the. 

Here I have created an excellent WYSIWYG HTML editor tool with all the necessary features and in a dark theme. 

files and folders for the WYSIWYG HTML editor

You want to create three files (indux.html, style.css and ) in a folder. 

index.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">
    <title>Document</title>
    <link rel="stylesheet" href="style.css">

</head>
<body>
    <div class="main">
        <center>
            <h1>Blog writer</h1>
        </center><br>

        <div class="textBlog">
            <form action="#" method="POST">
                <div class="options">

                    <!-- Text Format -->
                    <button type="button" id="bold" class="option-button format">
                        BOLD
                    </button>
                    <button type="button" id="italic" class="option-button format">
                        ITALIC
                    </button>
                    <button type="button" id="underline" class="option-button format">
                        UNDERLINE
                    </button>
                    <button type="button" id="strikethrough" class="option-button format">
                        STRICK
                    </button>
                    <button type="button" id="superscript" class="option-button script">
                        SUP
                    </button>
                    <button type="button" id="subscript" class="option-button script">
                        SUB
                    </button>
                    <!-- List -->
                    <button type="button" id="insertOrderedList" class="option-button">
                        OL
                    </button>
                    <button type="button" id="insertUnorderedList" class="option-button">
                        LI
                    </button>
                    <!-- Undo/Redo -->
                    <button type="button" id="undo" class="option-button">
                        UNDO
                    </button>
                    <button type="button" id="redo" class="option-button">
                        REDO
                    </button>

                    <!-- Link -->
                    <button type="button" id="createLink" class="adv-option-button">
                        LINK
                    </button>

                    <button type="button" id="unlink" class="option-button">
                        UNLINK
                    </button>

                    <!-- Alignment -->

                    <button type="button" id="justifyLeft" class="option-button align">
                        LEFT
                    </button>
                    <button type="button" id="justifyCenter" class="option-button align">
                        CENTER
                    </button>

                    <button type="button" id="justifyRight" class="option-button align">
                        RIGHT
                    </button>

                    <button type="button" id="justifyFull" class="option-button align">
                        JF
                    </button>

                    <button type="button" id="indent" class="option-button spacing">
                        INTENT
                    </button>

                    <button type="button" id="outdent" class="option-button spacing">
                        OUTDENT
                    </button>

                    <!-- Headings -->

                    <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>

                    <!-- Color -->

                    <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 name="mainContent" class="textCon" spellcheck="true" id="text-input" contenteditable="true">
                    <p></p>
                    <p></p>
                </div>
            </form>
        </div>
    </div>

    <div class="count">
        <div class="maincou">
            Post Words: <span id="pword" class="colorWord pword words">0</span>
        </div>
    </div>

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

    <script>
        document.getElementById('text-input').addEventListener('input', function () {
            var text = this.textContent,
                count = text.trim().replace(/s+/g, ' ').split(' ').length;
            document.querySelector('.words').textContent = count;
        });
    </script>    
</body>
</html>





style.css

* {
    margin: 0%;
    padding: 0%;
    box-sizing: border-box;
    font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}

body {
    background-color: rgb(6, 6, 20);
    color: rgb(139, 140, 141);
}

.textBlog {
    max-width: 800px;
    margin: auto;
    border: 1px solid rgb(126, 119, 119);
    border-radius: 12px;
    padding: 30px;
}

.textCon {
    height: 400px;
    overflow: auto;
    border: none;
    background-color: rgb(13, 13, 37);
    border-radius: 10px;
    outline: none;
    color: rgb(173, 169, 169);
    font-size: 20px;
    padding: 10px 20px;
    font-weight: 520;
}

.textCon p {
    padding: 15px 0 15px 0;
}

.textCon b {
    font-weight: 900;
}

.buttons {
    color: rgb(169, 173, 169);
    background-color: rgb(50, 0, 187);
    padding: 8px;
    font-size: 19px;
    font-weight: 800;
    border: none;
    margin: 20px 20px 20px 0;
    border-radius: 5px;
}

.buttons:hover {
   background-color: rgb(221, 221, 221);
    color: black;
}

::selection {
    background-color: rgb(255, 102, 0);
    color: white;
}

.count {
   position: absolute;
    top: 35px;
    left: 33px;
    display: inline-block;
    position: fixed;
}

.maincou {
    width: 300px;
    border: 2px solid rgb(255, 255, 255);
    color: rgb(224, 224, 224);
    background-color: rgb(11, 57, 207);
    border-radius: 30px;
    padding: 20px;
    font-weight: 600;
}

.colorWord {
    font-weight: 800;
    margin-left: 10px;
    color: rgb(255, 255, 255);
}

.textCon::-webkit-scrollbar {
    width: 4px;
}

.textCon::-webkit-scrollbar-track {
    background-color: rgb(51, 51, 51);
}

.textCon::-webkit-scrollbar-thumb {
    background-color: rgb(52, 89, 253);
}

.options button,
.options select {
    padding: 10px;
    background-color: blue;
    border: none;
   margin-bottom: 15px;
    color: white;
    outline: none;
    font-weight: 700;
}

.options button:hover,
.options select:hover {
    color: black;
    background-color: white;
}

.active {
    background-color: #e0e9ff;
}




main.js


let optionsButtons = document.querySelectorAll(".option-button");
let advancedOptionButton = document.querySelectorAll(".adv-option-button");
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");
//Initial Settings
const initializer = () => { 

  //No highlights for link, unlink,lists, undo,redo since they are one time operations
  highlighter(alignButtons, true);
  highlighter(spacingButtons, true);
  highlighter(formatButtons, false);
  highlighter(scriptButtons, true);

  //create options for font names
  fontList.map((value) => {
    let option = document.createElement("option");
    option.value = value;
    option.innerHTML = value;
    fontName.appendChild(option);
  });

  //default size
  fontSizeRef.value = 3;
};

//main logic
const modifyText = (command, defaultUi, value) => {
  //execCommand executes command on selected text
  document.execCommand(command, defaultUi, value);
};

//For basic operations which don't need value parameter
optionsButtons.forEach((button) => {
  button.addEventListener("click", () => {
    modifyText(button.id, false, null);
  });

});

//options that require value parameter (e.g colors, fonts)
advancedOptionButton.forEach((button) => {
  button.addEventListener("change", () => {
    modifyText(button.id, false, button.value);
  });
});

//link
linkButton.addEventListener("click", () => {
  let userLink = prompt("Enter a URL");
  //if link has http then pass directly else add https
  if (/http/i.test(userLink)) {
   modifyText(linkButton.id, false, userLink);
  } else {
    userLink = "http://" + userLink;
    modifyText(linkButton.id, false, userLink);
  }
});

//Highlight clicked button
const highlighter = (className, needsRemoval) => {
  className.forEach((button) => {
    button.addEventListener("click", () => {
      //needsRemoval = true means only one button should be highlight and other would be normal
      if (needsRemoval) {
        let alreadyActive = false;
       //If currently clicked button is already active
       if (button.classList.contains("active")) {
         alreadyActive = true;
        }

        //Remove highlight from other buttons
        highlighterRemover(className);
        if (!alreadyActive) {
         //highlight clicked button
          button.classList.add("active");
       }
      } else {
        //if other buttons can be highlighted
        button.classList.toggle("active");
      }
    });
  });

};

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

  });
};

window.onload = initializer();




You might like:

  1. How to make an HTML-to-PDF converter? HTML to PDF - JS library
  2. Detect browser using JavaScript - with source code
  3. Download button with counter using HTML CSS and JavaScript 
  4. How to create an Internet status viewer using JavaScript?
  5. Words counter with stylish dark UI using HTML CSS and JS

Discussions

  1. Anonymous2:35 AM

    How to add about us, contact under website I applied your theme on my blog it redirects to this website




    ReplyDelete