Rich text editor using HTML CSS and JavaScript with words counter


In embarking on this web development journey, I am excited to take on the challenge of creating a remarkable and unforgettable project. The task at hand is to design and develop a sophisticated rich text editor, one that not only offers the standard functionality but also boasts a stunning dark theme to enhance the user experience.

As I delve into the intricacies of building this editor, I will undoubtedly encounter numerous learning opportunities. These will range from honing my coding skills to grasping the nuances of designing an intuitive user interface. The knowledge gained during this process will undoubtedly be invaluable, leaving a lasting impact on my web development career.

In this endeavor, I envision overcoming obstacles, solving intricate problems, and discovering innovative solutions. Every step of the way, I will be pushing my boundaries, expanding my skillset, and embracing new technologies. This journey promises to be filled with excitement and growth.

Moreover, the dark theme, with its elegance and visual appeal, will set this project apart from others. It will showcase my ability to create not only functional but also aesthetically pleasing digital experiences. Users will appreciate the ease of their eyes and the modern touch this theme brings.

As I prepare to unveil the project, I cannot help but feel a sense of pride and satisfaction in what I've accomplished. This endeavor will undoubtedly be etched into my memory as a defining moment in my web development career.

Finally, I am deeply grateful to share the source code with the community. By doing so, I hope to inspire and support other aspiring developers on their journeys. Remember, knowledge grows when shared, and I encourage everyone to pass on the experience to others.

So, if you find value in this project, I encourage you to share it with your friends, colleagues, and fellow developers. Together, we can foster a culture of learning and collaboration, enriching the web development community as a whole.

With enthusiasm and determination, I embark on this path, knowing that this project will leave a meaningful impact not just on my career but also on those who use and learn from it. Let the journey begin!

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

What is a rich text editor?

The term "Rich Text Editor" is a simplified reference to a WYSIWYG (What You See Is What You Get) HTML editor. This powerful tool empowers users to effortlessly compose, revise, and manage text content. The primary objective of a WYSIWYG HTML editor, often referred to as a rich text editor, is to streamline the process of coding while handling textual content. Within this tool, fundamental formatting options such as bold, italic, underline, headings, and hyperlinking are conveniently accessible. Furthermore, the tool can be enhanced with a diverse array of supplementary components, tailored to individual preferences and requirements.

Detect browser using JavaScript - with source code

Presenting an exceptional WYSIWYG HTML editor, meticulously crafted with an array of indispensable features, all meticulously unified within an elegant dark-themed interface. This thoughtful design not only promotes visual comfort but also embodies a user-centric approach to content creation. By seamlessly blending sophisticated functionality with an aesthetically pleasing design, this WYSIWYG HTML editor in a dark theme offers an unparalleled experience in crafting compelling and visually captivating web content.

files and folders for the WYSIWYG HTML editor

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

How to create an Internet status viewer using JavaScript?

index.html

This is the main HTML file that will contain the structure of the editor interface. You can include the necessary HTML elements, like the toolbar, editor area, and any other components needed for editing and displaying content.


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

This CSS file will be responsible for styling the WYSIWYG editor. You can customize the appearance of the toolbar, editor area, fonts, colors, etc., to create a visually appealing and user-friendly interface.
* {
    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

This JavaScript file will handle the interactive features of the editor, such as adding formatting options, handling user input, and updating the editor's content.

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();

Related Posts

Comments