Skip to content

Commit

Permalink
Merge pull request Sulagna-Dutta-Roy#547 from Sambit-Mondal/RichTextE…
Browse files Browse the repository at this point in the history
…ditor

Fixes Sulagna-Dutta-Roy#368
  • Loading branch information
Sulagna-Dutta-Roy authored May 30, 2024
2 parents 90ff368 + 0f93353 commit f23b25a
Show file tree
Hide file tree
Showing 6 changed files with 349 additions and 0 deletions.
Binary file added Rich Text Editor/game-28-128.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Rich Text Editor/game-28-48.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
112 changes: 112 additions & 0 deletions Rich Text Editor/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
<!DOCTYPE html>
<html lang="en">

<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Rich Text Editor</title>
<!-- FontAwesome Icons -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.1.1/css/all.min.css" />
<!-- Google Fonts -->
<link href="https://fonts.googleapis.com/css2?family=Poppins&display=swap" rel="stylesheet" />
<!-- Stylesheet -->
<link rel="stylesheet" href="src/style.css" />
</head>

<body>
<div class="container">
<div class="options">
<!-- Text Format -->
<button id="bold" class="option-button format">
<i class="fa-solid fa-bold"></i>
</button>
<button id="italic" class="option-button format">
<i class="fa-solid fa-italic"></i>
</button>
<button id="underline" class="option-button format">
<i class="fa-solid fa-underline"></i>
</button>
<button id="strikethrough" class="option-button format">
<i class="fa-solid fa-strikethrough"></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>

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

<!-- Undo/Redo -->
<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>

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

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

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

<!-- Font -->
<select id="fontName" class="adv-option-button"></select>
<select id="fontSize" class="adv-option-button"></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 id="text-input" contenteditable="true"></div>
</div>
<!--Script-->
<script src="scripts/script.js"></script>
</body>

</html>
30 changes: 30 additions & 0 deletions Rich Text Editor/manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{
"manifest_version": 3,
"name": "Rich Text Editor Extension JS",
"version": "1.0",
"description": "Rich text editor extension built in pure HTML CSS JS...",
"author": "[email protected]",
"icons": {
"48": "game-28-48.png",
"128": "game-28-128.png"
},
"permissions": [
"storage"
],
"optional-permissions": [
"tabs"
],
"action": {
"default_popup": "index.html"
},
"web_accessible_resources": [
{
"resources": [
"index.html"
],
"matches": [
"<all_urls>"
]
}
]
}
117 changes: 117 additions & 0 deletions Rich Text Editor/scripts/script.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
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");

//List of fontlist
let fontList = [
"Arial",
"Verdana",
"Times New Roman",
"Garamond",
"Georgia",
"Courier New",
"cursive",
];

//Initial Settings
const initializer = () => {
//function calls for highlighting buttons
//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);
});

//fontSize allows only till 7
for (let i = 1; i <= 7; i++) {
let option = document.createElement("option");
option.value = i;
option.innerHTML = i;
fontSizeRef.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();
90 changes: 90 additions & 0 deletions Rich Text Editor/src/style.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
* {
padding: 0;
margin: 0;
box-sizing: border-box;
}

body {
background-color: #338cf4;
overflow: hidden;
}

.container {
background-color: #ffffff;
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 {
height: 28px;
width: 28px;
display: grid;
place-items: center;
border-radius: 3px;
border: none;
background-color: #ffffff;
outline: none;
color: #020929;
}

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

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

.input-wrapper {
display: flex;
align-items: center;
gap: 8px;
}

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 #ffffff, 0 0 0 3px #020929;
}

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

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

.active {
background-color: #e0e9ff;
}

0 comments on commit f23b25a

Please sign in to comment.