// Add an external book
let inupt = document.getElementById("external-book");
let ptn = document.getElementById("add-external-book");
let settings = document.getElementById("add-settings");
// _____________________start add_____________________________________
let myAddText = [];
function textAddSettings() {
settings.innerHTML = "";
let index = 0;
for (task of myAddText) {
let content = `
<div class="settings">
<h4 class="book-name">${task.name}</h4>
<button id ="asx" onclick="missionCompleted(${index})" class="button-css">ending</button>
</div>
`;
settings.innerHTML += content;
index++;
}
};
ptn.addEventListener("click", function () {
let textBk = inupt.value;
let myAddTextObjkt = {
name: textBk,
removeLeFather: ""
};
myAddText.push(myAddTextObjkt);
//innerHTML
textAddSettings();
inupt.value = '';
});
// ___________________Department of Executed Tasks____________________
let executedTasks = document.getElementById("executed-tasks");
let execute = [];
function textAddExecute() {
executedTasks.innerHTML = "";
let index = 0;
for (task of execute) {
let content =
`
<div class="all-tasks-box">
<div class="my-list">
<h4 class="book-name">${task.name}</h4>
<div class="all-star">
<button onclick="changeColorPnt(${index})" id = "nx" class="button-css">Notes</button>
</div>
</div>
<div class="text-box-m xxxxx ${task.showAndNoneBox ? "show-none" : ""}">
<textarea id = "taw" class="${task.colorArea ? "color-green" : "color-white"}" type ="text" ${task.textAreaReadonly ? "readonly" : ""} > ${task.textareaValue}</textarea>
<button onclick="editAndSave(${index})" >${task.editTextArea ? "Edit" : "save"}</button>
</div>
</div>
`;
executedTasks.innerHTML += content;
index++;
}
};
// Adds the element to the new array while deleting the element from the old array
function missionCompleted(index) {
// task name
let element = myAddText[index].name;
let myexecute = {
name: element,
showAndNoneBox: "false",
textAreaReadonly: "true",
colorArea: "true",
textareaValue: "false",
editTextArea: "false"
};
execute.push(myexecute);
textAddExecute();
// delete the element from the old array
// We will get the index of the item and delete it
myAddText.splice(index, 1);
//innerHTML Updates the old text data
textAddSettings();
};
// ________________Notes button__________________________
function changeColorPnt(index) {
let element = execute[index];
if (element.showAndNoneBox) {
// text area
element.showAndNoneBox = false;
element.textAreaReadonly = false;
} else {
// text area
element.showAndNoneBox = true;
}
textAddExecute();
};
//_____________________________
function editAndSave(index) {
let btn = execute[index];
if (btn.editTextArea) {
// edit or save button
btn.editTextArea = false;
// The text area is allowed to write in
btn.textAreaReadonly = false;
// Change the color of the text area
btn.colorArea = false;
btn.textareaValue = document
.querySelector(`.text-box-m textarea`)
.value.trim();
} else {
btn.textareaValue = document
.querySelector(`.text-box-m textarea`)
.value.trim();
// Modify button
btn.editTextArea = true;
// The text area is not allowed to be written in
btn.textAreaReadonly = true;
// Change the color of the text area
btn.colorArea = true;
}
textAddExecute();
};
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
direction:rtl;
}
.contnire {
margin: 0 auto;
min-height: 100vh;
width: 900px;
background-color: #176a63;
}
/* Start title */
.contnire .title {
width: 100%;
height: 70px;
background-color: #176a63;
display: flex;
align-items: center;
justify-content: space-around;
}
.contnire .title .add-book {
display: flex;
width: 200px;
height: 25px;
}
.contnire .title .add-book input:focus {
background-color: aquamarine;
outline: none;
}
.contnire .title h1 {
text-align: center;
margin-right: 200px;
color: white;
padding: 20px;
font-size: 40px;
}
/* End title */
/* Start box-body */
.box-body {
display: flex;
flex-direction: column;
padding: 20px;
background-color: #3F51B5;
width: 100%;
}
/* Start content */
.content {
padding: 20px;
background-color: white;
border-bottom: 2px solid #7044b2;
box-shadow: 0px -1px 13px 4px #b9b3b3;
}
/* Start box */
.content .box {
text-align: center;
background-color: #009688;
width: 100%;
}
.box .mybox {
display: flex;
align-items: center;
justify-content: center;
background-color: #3F51B5;
}
.box .mybox h3 {
padding: 20px;
}
.content .control-book .settings {
display: flex;
align-items: center;
height: 50px;
border-bottom: 2px solid #ccc;
padding: 5px;
}
/* End box */
/* End content */
/* Start box-down */
.box-down .add-list {
display: flex;
padding-top: 20px;
justify-content: space-around;
}
.add-list .Waiting-list-two {
width: calc(100% - 10px);
}
.add-list .my-list-one {
background-color: #7044b2;
}
.add-list .my-list-one h2 {
padding: 20px;
}
.add-list .my-list {
padding: 5px;
background-color: #009688;
display: flex;
align-items: center;
justify-content: space-between;
border-bottom: 2px solid #ccc;
}
/* End box-down */
/* all */
.button-css {
padding: 4px 10px;
margin-right: 4px;
}
.book-name {
padding: 10px;
width: 220px;
background-color: #f9f3f3fa;
}
textarea {
padding: 5px;
line-height: 1.6;
word-spacing: -6px;
overflow: auto;
width: 100%;
height: 100px;
font-size: 18px;
}
textarea:disabled {
color: #000000e6;
background-color: #8bc34a57;
}
.show-none {
display: none;
}
textarea.color-green {
background-color: #4caf505e;
}
textarea.color-white {
background-color: white;
}
<div class="contnire">
<!-- Start title -->
<div class="title">
<div class="add-book">
<input id="external-book" class="book-name" type="text">
<button id="add-external-book" class="button-css">add</button>
</div>
<h1>My tasks</h1>
</div>
<!-- End title -->
<!-- Start box-body -->
<div class="box-body">
<!-- Start content -->
<div class="content">
<!-- Start box -->
<div class="box">
<div class="mybox">
<h3>required tasks</h3>
</div>
<div id="add-settings" class="control-book"></div>
</div>
<!-- End box -->
</div>
<!-- End content -->
<!-- Start box-down -->
<div class="box-down">
<div class="add-list">
<div class="Waiting-list-two">
<div class="my-list-one">
<h2>The tasks that were performed</h2>
</div>
<div id="executed-tasks" class="all-list">
</div>
</div>
</div>
<!-- End box-down -->
</div>
</div>
</div>
I write the name of the task, then press the "Add" button, the item appears, and next to it the "Finish" button. When I press Finish, the item appears in the To Do section, and next to the item, the Notes button. When I press the notes button, the text area appears and disappears, and in the text area there is an edit button. When I click on it I can type a comment inside the text area, and by pressing the save button the edit is locked into the problematic text area? When I add more than one element the entire text area takes the same as the first comment and I want each element to be stable writing the text area so I can modify the comment in any element without affecting the rest
const addBtn = document.querySelector(".add");
const modal = document.querySelector(".modal__container");
const library = document.querySelector(".library__container");
const submitBook = document.querySelector(".add__book");
const deleteBtn = document.querySelector(".fas fa-trash-alt");
//Modal inputs
const modalTitle = document.querySelector("#title");
const modalAuthor = document.querySelector("#author");
const modalPages = document.querySelector("#pages");
const isRead = document.querySelector("#read-status");
//Toggle Modal
const hideModal = () => {
modal.style.display = "none";
};
const showModal = () => {
modal.style.display = "block";
const cancel = document.querySelector(".cancel");
cancel.addEventListener("click", (e) => {
e.preventDefault();
hideModal();
});
};
addBtn.addEventListener("click", showModal);
let myLibrary = [];
let index = 0;
function Book(title, author, pages, read) {
this.title = title,
this.author = author,
this.pages = pages,
this.read = read
}
submitBook.addEventListener("click", addBookToLibrary);
function addBookToLibrary(e) {
e.preventDefault();
let bookTitle = modalTitle.value;
let bookAuthor = modalAuthor.value;
let bookPages = modalPages.value;
let bookStatus = isRead.checked;
//Display error message if inputs are empty
if (bookTitle === "" || bookAuthor === "" || bookPages === "") {
const errorMessage = document.querySelector(".error__message--container");
hideModal();
errorMessage.style.display = "block";
const errorBtn = document.querySelector(".error-btn");
errorBtn.addEventListener("click", () => {
errorMessage.style.display = "none";
showModal();
})
} else {
let book = new Book(bookTitle, bookAuthor, bookPages, bookStatus);
myLibrary.push(book);
hideModal();
render();
}
}
function render() {
library.innerHTML = "";
for (let i = 0; i < myLibrary.length; i++) {
library.innerHTML +=
'<div class="book__container">' +
'<div class="book">' +
'<div class="title__content">' +
'<span class="main">Title : </span><span class="book__title">' +` ${myLibrary[i].title}`+'</span>' +
'</div>' +
'<div class="author__content">' +
'<span class="main">Author : </span><span class="book__author">'+` ${myLibrary[i].author}`+'</span>' +
'</div>' +
'<div class="pages__content">' +
'<span class="main">Pages : </span><span class="book__pages">'+` ${myLibrary[i].pages}`+'</span>' +
'</div>' +
'<div class="book__read-elements">' +
'<span class="book__read">I read it</span>' +
'<i class="fas fa-check"></i>' +
'<a href="#"><i class="fas fa-times"></i>' +
'<i class="fas fa-trash-alt"></i>' +
'</div>' +
'</div>' +
'</div>'
readStatus(myLibrary[i].checked)
}
modalTitle.value = "";
modalAuthor.value = "";
modalPages.value = "";
isRead.checked = false;
}
function readStatus(bookStatus) {
const bookStatusContainer = document.querySelector(".book__read");
if (bookStatus) {
bookStatusContainer.classList.add("yes");
bookStatusContainer.textContent = "I read it";
bookStatusContainer.style.color = "rgb(110, 176, 120)";
} else {
bookStatusContainer.classList.add("no");
bookStatusContainer.textContent = "I have not read it";
bookStatusContainer.style.color = "rgb(194, 89, 89)";
}
}
#import url('https://fonts.googleapis.com/css2?family=Poppins:wght#300;400;600&display=swap');
:root {
--light-gray: #dededef3;
--title-color: #333756;
--main-color: #c6c6c6f3;
}
* {
padding: 0;
margin: 0;
box-sizing: border-box;
}
body {
font-family: 'Poppins', sans-serif;
background-color: var(--light-gray);
}
header {
text-align: center;
padding-top: 4rem;
color: var(--title-color);
text-transform: uppercase;
letter-spacing: 4px;
}
button {
margin: 1rem;
padding: 0.8rem 2rem;
font-size: 14px;
border-radius: 25px;
background: white;
color: #333756;
font-weight: 600;
border: none;
cursor: pointer;
transition: 0.6s all ease;
}
:focus {
/*outline: 1px solid white;*/
}
button:hover {
background: var(--title-color);
color: white;
}
.add__book:hover,
.cancel:hover {
background: var(--main-color);
color: var(--title-color)
}
.all,
.books__read,
.books__not-read {
border-radius: 0;
text-transform: uppercase;
letter-spacing: 0.1rem;
background: var(--light-gray);
border-bottom: 4px solid var(--title-color)
}
.library__container {
display: flex;
justify-content: center;
flex-wrap: wrap;
}
.book__container {
display: flex;
margin: 2rem 2rem;
}
.modal__container {
display: none;
position: fixed;
z-index: 4;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.4);
padding-top: 0px;
}
.book,
.modal {
padding: 2rem 2rem;
border-radius: 15px;
background: #333756;
line-height: 3rem;
}
.modal {
position: relative;
width: 50%;
margin: 0 auto;
margin-top: 8rem;
}
.modal__content {
display: flex;
flex-direction: column;
}
label {
color: white;
margin-right: 1rem;
}
input {
padding: 0.5rem;
font-size: 14px;
}
.book__read-elements {
display: flex;
justify-content: space-between;
}
.main,
i {
color: white;
pointer-events: none;
margin: 0.5rem;
}
.book__title,
.book__author,
.book__pages,
.book__read {
color: var(--main-color)
}
.error__message--container {
display: none;
position: fixed;
z-index: 4;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.4);
}
.error__message--modal {
position: relative;
margin: 0 auto;
margin-top: 10rem;
width:40%;
}
.error {
display: flex;
flex-direction: column;
align-items: center;
color: rgb(101, 3, 3);
font-size: 20px;
font-weight: bold;
background: rgb(189, 96, 96);
padding: 3rem 5rem;
border-radius: 10px;
}
.error-btn {
color: rgb(101, 3, 3);
font-weight: bold;
}
.error-btn:hover {
color: white;
background: rgb(101, 3, 3);
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.13.1/css/all.min.css" integrity="sha256-2XFplPlrFClt0bIdPgpz8H7ojnk10H69xRqd9+uTShA=" crossorigin="anonymous" />
<link rel="stylesheet" href="styles.css">
<title>Library</title>
</head>
<body>
<header>
<h1>My Library</h1>
<button class="add">Add New Book</button>
<div class="buttons">
<button class="all">View All</button>
<button class="books__read">Read</button>
<button class="books__not-read">Not Read</button>
</div>
</header>
<div class="error__message--container">
<div class="error__message--modal">
<div class="error">
<p>Complete the form!</p>
<button class ="error-btn">Ok</button>
</div>
</div>
</div>
<!--Modal-->
<form class="modal__container">
<div class="modal">
<div class="modal__content">
<label for="">Title:</label>
<input type="text" id="title">
</div>
<div class="modal__content">
<label for="">Author:</label>
<input type="text" id="author">
</div>
<div class="modal__content">
<label for="">Pages:</label>
<input type="number" id="pages">
</div>
<div>
<label for="read-status">Check the box if you've read this book</label>
<input type="checkbox" id="read-status" value ="check">
</div>
<button class="add__book">Add</button>
<button class="cancel">Cancel</button>
</div>
</form>
<!--End of Modal-->
<div class="library__container"></div>
<script src="script.js"></script>
</body>
</html>
I'm new to OOP and I'm struggling.
I'm building a library where you can add a book with the title, author nr of pages and if you've read it or not. When I add the first book if I check the box it displays that to book is not read(which is false). When I add a new book the read functionality is not applied to that book at all. I have no idea how to fix it
In this function you are checking the status if isRead which is incorrect.
Do this
Call the readStatus function inside the for loop
Pass the current parameter readStatus(myLibrary[i].checked)
Modify readStatus as shown below
function readStatus(status) {
const bookReadStatus = document.querySelector(".book__read");
if (status) {
bookReadStatus.classList.add("yes");
bookReadStatus.textContent = "I read it";
bookReadStatus.style.color = "rgb(110, 176, 120)";
} else {
bookReadStatus.classList.add("no");
bookReadStatus.textContent = "I have not read it";
bookReadStatus.style.color = "rgb(194, 89, 89)";
}
}
So, I made a calculator, and I want to add a square root function, but I know there is no already made function that finds the square root of numbers. So what elements can I combine to find the square root of a number?
const screen = document.querySelector("#screen");
const clearButton = document.querySelector("#clear");
const equalsButton = document.querySelector("#equals");
const decimalButton = document.querySelector("#decimal");
let isFloat = false;
let signOn = false;
let firstNumber = "";
let operator = "";
let secondNumber = "";
let result = "";
const allClear = () => {
isFloat = false;
signOn = false;
firstNumber = "";
operator = "";
secondNumber = "";
result = "";
screen.value = "0";
};
const calculate = () => {
if (operator && result === "" && ![" ", "+", "-", "."].includes(screen.value[screen.value.length - 1])) {
secondNumber = screen.value.substring(firstNumber.length + 3);
switch (operator) {
case "+":
result = Number((Number(firstNumber) + Number(secondNumber)).toFixed(3));
break;
case "-":
result = Number((Number(firstNumber) - Number(secondNumber)).toFixed(3));
break;
case "*":
result = Number((Number(firstNumber) * Number(secondNumber)).toFixed(3));
break;
case "/":
result = Number((Number(firstNumber) / Number(secondNumber)).toFixed(3));
break;
default:
}
screen.value = result;
}
};
clear.addEventListener("click", allClear);
document.querySelectorAll(".number").forEach((numberButton) => {
numberButton.addEventListener("click", () => {
if (screen.value === "0") {
screen.value = numberButton.textContent;
} else if ([" 0", "+0", "-0"].includes(screen.value.substring(screen.value.length - 2))
&& numberButton.textContent === "0") {
} else if ([" 0", "+0", "-0"].includes(screen.value.substring(screen.value.length - 2))
&& numberButton.textContent !== "0") {
screen.value = screen.value.substring(0, screen.value.length - 1) + numberButton.textContent;
} else if (result || result === 0) {
allClear();
screen.value = numberButton.textContent;
} else {
screen.value += numberButton.textContent;
}
});
});
decimalButton.addEventListener("click", () => {
if (result || result === 0) {
allClear();
isFloat = true;
screen.value += ".";
} else if (!isFloat) {
isFloat = true;
if ([" ", "+", "-"].includes(screen.value[screen.value.length - 1])) {
screen.value += "0.";
} else {
screen.value += ".";
}
}
});
document.querySelectorAll(".operator").forEach((operatorButton) => {
operatorButton.addEventListener("click", () => {
if (result || result === 0) {
isFloat = false;
signOn = false;
firstNumber = String(result);
operator = operatorButton.dataset.operator;
result = "";
screen.value = `${firstNumber} ${operatorButton.textContent} `;
} else if (operator && ![" ", "+", "-", "."].includes(screen.value[screen.value.length - 1])) {
calculate();
isFloat = false;
signOn = false;
firstNumber = String(result);
operator = operatorButton.dataset.operator;
result = "";
screen.value = `${firstNumber} ${operatorButton.textContent} `;
} else if (!operator) {
isFloat = false;
firstNumber = screen.value;
operator = operatorButton.dataset.operator;
screen.value += ` ${operatorButton.textContent} `;
} else if (!signOn
&& !["*", "/"].includes(operatorButton.dataset.operator)
&& screen.value[screen.value.length - 1] === " ") {
signOn = true;
screen.value += operatorButton.textContent;
}
});
});
equalsButton.addEventListener("click", calculate);
* {
box-sizing: border-box;
font-family: 'Roboto', sans-serif;
font-weight: 300;
margin: 0;
padding: 0;
}
body {
background-color: #222;
height: 100vh;
}
header {
background-color: #333;
padding: 40px 0;
}
header h1 {
-webkit-background-clip: text;
background-clip: text;
background-image: linear-gradient(to right bottom, #fff, #777);
color: transparent;
font-size: 40px;
letter-spacing: 2px;
text-align: center;
text-transform: uppercase;
}
main {
background-color: #222;
display: flex;
justify-content: center;
padding: 60px 0;
}
main #container {
background-color: #333;
box-shadow: 0 5px 5px #111;
padding: 20px;
}
.clearfix:after {
clear: both;
content: " ";
display: block;
font-size: 0;
height: 0;
visibility: hidden;
}
#container .row:not(:last-child) {
margin-bottom: 9px;
}
#container input,
#container button {
float: left;
}
#container input:focus,
#container button:focus {
outline: none;
}
#container input {
background-color: #222;
border: 1px solid #999;
border-right-width: 0;
color: #999;
font-size: 22px;
font-weight: 300;
height: 80px;
padding-right: 14px;
text-align: right;
width: 261px;
}
#container button {
background-color: #222;
border: none;
box-shadow: 0 3px 0 #111;
color: #999;
font-size: 20px;
height: 80px;
margin-right: 7px;
width: 80px;
}
#container button:active {
box-shadow: 0 2px 0 #111;
transform: translateY(1px);
}
#container #clear,
#container .operator,
#container #equals {
color: #111;
}
#container #clear,
#container .operator {
margin-right: 0;
}
#container #clear {
background-color: #e95a4b;
border: 1px solid #999;
border-left-width: 0;
box-shadow: none;
cursor: pointer;
}
#container #clear:active {
box-shadow: none;
transform: none;
}
#container .operator {
background-color: #999;
box-shadow: 0 3px 0 #555;
}
#container .operator:active {
box-shadow: 0 2px 0 #555;
}
#container #equals {
background-color: #2ecc71;
box-shadow: 0 3px 0 #155d34;
}
#container #equals:active {
box-shadow: 0 2px 0 #155d34;
}
#media only screen and (max-width: 400px) {
header {
padding: 28px 0;
}
header h1 {
font-size: 36px;
}
main {
padding: 40px 0;
}
main #container {
padding: 16px;
}
#container .row:not(:last-child) {
margin-bottom: 7px;
}
#container input {
font-size: 18px;
height: 60px;
padding-right: 10px;
width: 195px;
}
#container button {
font-size: 16px;
height: 60px;
margin-right: 5px;
width: 60px;
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<title>Calculator</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="https://fonts.googleapis.com/css?family=Roboto:300" rel="stylesheet">
<link href="Project 1.css" rel="stylesheet">
</head>
<body>
<header>
<h1>Calculator</h1>
</header>
<main>
<div id="container">
<div class="row clearfix">
<input id="screen" value="0" disabled type="text">
<button id="clear">AC</button>
</div>
<div class="row clearfix">
<button class="number">1</button>
<button class="number">2</button>
<button class="number">3</button>
<button data-operator="+" class="operator">+</button>
</div>
<div class="row clearfix">
<button class="number">4</button>
<button class="number">5</button>
<button class="number">6</button>
<button data-operator="-" class="operator">-</button>
</div>
<div class="row clearfix">
<button class="number">7</button>
<button class="number">8</button>
<button class="number">9</button>
<button data-operator="*" class="operator">×</button>
</div>
<div class="row clearfix">
<button id="decimal">.</button>
<button class="number">0</button>
<button id="equals">=</button>
<button data-operator="/" class="operator">÷</button>
</div>
</div>
</main>
<script src="Project 1.js"></script>
</body>
</html>
This is the code for the calc.. Feel free to edit it and explain to me what you did.
There is already one.
The Math.sqrt() function returns the square root of a number, that is, ∀x≥0,Math.sqrt(x)=x
=the uniquey≥0such thaty2=x
MDN Docs
You can use javascript built in
Math.sqrt(number)
I have got a problem at the coding project I am doing, as I formatted the numbers to be shown nicer, I ran into a problem. The webpage when it loads shows NaN. undefined in the total income/expenses at the top. I can't figure out what is the problem.
//Budget controller
var budgetController = (function() {
var Expense = function(id, description, value) {
this.id = id;
this.description = description;
this.value = value;
this.percentage = -1;
};
Expense.prototype.calcPercentage = function(totalIncome) {
if (totalIncome > 0) {
this.percentage = Math.round((this.value / totalIncome) * 100);
} else {
this.percentage = -1;
}
};
Expense.prototype.getPercentage = function() {
return this.percentage;
};
var Income = function(id, description, value) {
this.id = id;
this.description = description;
this.value = value;
};
var calculateTotal = function(type) {
var sum = 0;
data.allItems[type].forEach(function(cur) {
sum = sum + cur.value;
});
data.totals[type] = sum;
};
var data = {
allItems: {
exp: [],
inc: []
},
totals: {
exp: 0,
inc: 0
},
budget: 0,
percentage: -1
};
return {
addItem: function(type, des, val) {
var newItem, ID;
//create new iD
if (data.allItems[type].length > 0) {
ID = data.allItems[type][data.allItems[type].length - 1].id + 1;
} else {
ID = 0;
}
//CREATe new item, if it is inc or exp
if (type === 'exp') {
newItem = new Expense(ID, des, val);
} else if (type === 'inc') {
newItem = new Income(ID, des, val);
}
// Push all items into data structure and return the new element
data.allItems[type].push(newItem);
return newItem;
},
deleteItem: function(type, id) {
var ids, index;
ids = data.allItems[type].map(function(current) {
return current.id;
});
index = ids.indexOf(id);
if (index !== -1) {
data.allItems[type].splice(index, 1);
}
},
calculateBudget: function() {
// calculate the total income and expenses
calculateTotal('exp');
calculateTotal('inc');
// calculate the budget: income - expenses
data.budget = data.totals.inc - data.totals.exp;
if (data.totals.inc > 0) {
data.percentage = Math.round((data.totals.exp / data.totals.inc) * 100);
} else {
data.percentage = -1;
}
},
calculatePercentages: function() {
data.allItems.exp.forEach(function(cur) {
cur.calcPercentage(data.totals.inc);
});
},
getPercentages: function() {
var allPerc = data.allItems.exp.map(function(cur) {
return cur.getPercentage();
});
return allPerc;
},
getBudget: function() {
return {
budget: data.budget,
totalInc: data.totals.inc,
totalExp: data.totals.exp,
percentage: data.percentage
};
}
};
})();
// UI Controller
var UIController = (function() {
var DOMstrings = {
inputType: '.add__type',
inputDescription: '.add__description',
inputValue: '.add__value',
inputBtn: '.add__btn',
incomeContainer: '.income__list',
expensesContainer: '.expenses__list',
budgetLabel: '.budget__value',
incomeLabel: '.budget__income--value',
expensesLabel: '.budget__expenses--value',
percentageLabel: '.budget__expenses--percentage',
container: '.container',
expensesPercLabel: '.item__percentage',
dateLabel: '.budget__title--month'
};
var formatNumber = function(num, type) {
var numSplit, int, dec, type;
/* + or - befofe a number
on 2 decimals
comma seperating thousands
*/
num = Math.abs(num);
num = num.toFixed(2);
numSplit = num.split('.');
int = numSplit[0];
if (int.length > 3) {
int = int.substr(0, int.length - 3) + ',' + int.substr(int.length - 3, 3); //input 23510, output 23,510
}
dec = numSplit[1];
return (type === 'exp' ? '-' : '+') + ' ' + int + '.' + dec;
};
var nodeListForEach = function(list, callback) {
for (var i = 0; i < list.length; i++) {
callback(list[i], i);
}
};
return {
getInput: function() {
return {
type: document.querySelector(DOMstrings.inputType).value, //will be either inc or exp
description: document.querySelector(DOMstrings.inputDescription).value,
value: parseFloat(document.querySelector(DOMstrings.inputValue).value)
};
},
addListItem: function(obj, type) {
var html, newHtml, element;
// Create HTML string with placeholder text
if (type === 'inc') {
element = DOMstrings.incomeContainer;
html = '<div class="item clearfix" id="inc-%id%"> <div class="item__description">%description%</div><div class="right clearfix"><div class="item__value">%value%</div><div class="item__delete"><button class="item__delete--btn"><i class="ion-ios-close-outline"></i></button></div></div></div>';
} else if (type === 'exp') {
element = DOMstrings.expensesContainer;
html = '<div class="item clearfix" id="exp-%id%"><div class="item__description">%description%</div><div class="right clearfix"><div class="item__value">%value%</div><div class="item__percentage">21%</div><div class="item__delete"><button class="item__delete--btn"><i class="ion-ios-close-outline"></i></button></div></div></div>';
}
// Replace the placeholder text with some actual data
newHtml = html.replace('%id%', obj.id);
newHtml = newHtml.replace('%description%', obj.description);
newHtml = newHtml.replace('%value%', formatNumber(obj.value, type));
// Insert the HTML into the DOM
document.querySelector(element).insertAdjacentHTML('beforeend', newHtml);
},
deleteListItem: function(selectorID) {
var el = document.getElementById(selectorID);
el.parentNode.removeChild(el);
},
clearFields: function() {
var fields, fieldsArr;
fields = document.querySelectorAll(
DOMstrings.inputDescription + ',' + DOMstrings.inputValue
);
fieldsArr = Array.prototype.slice.call(fields);
fieldsArr.forEach(function(current, index, array) {
current.value = "";
});
fieldsArr[0].focus();
},
displayBudget: function(obj) {
var type;
obj.budget > 0 ? type = 'inc' : type = 'exp';
document.querySelector(DOMstrings.budgetLabel).textContent = formatNumber(obj.budget, type);
document.querySelector(DOMstrings.incomeLabel).textContent = formatNumber(obj.totalInc, 'inc');
document.querySelector(DOMstrings.expensesLabel).textContent = formatNumber(obj.totalExp, 'exp');
if (obj.percentage > 0) {
document.querySelector(DOMstrings.percentageLabel).textContent = obj.percentage + '%';
} else {
document.querySelector(DOMstrings.percentageLabel).textContent = '---';
}
},
displayPercentages: function(percentages) {
var fields = document.querySelectorAll(DOMstrings.expensesPercLabel);
nodeListForEach(fields, function(current, index) {
if (percentages[index] > 0) {
current.textContent = percentages[index] + '%';
} else {
current.textContent = '---';
}
});
},
getDOMstrings: function() {
return DOMstrings;
}
};
})();
// App Controller - global
var controller = (function(budgetCtrl, UICtrl) {
var setupEventListeners = function() {
var DOM = UICtrl.getDOMstrings();
document.querySelector(DOM.inputBtn).addEventListener('click', ctrlAddItem);
document.addEventListener('keypress', function(event) {
if (event.keyCode === 13 || event.which === 13) {
ctrlAddItem();
}
});
document.querySelector(DOM.container).addEventListener('click', ctrlDeleteItem);
};
var updateBudget = function() {
// 1. Calculate the budget
budgetCtrl.calculateBudget();
// 2. Return the budget
var budget = budgetCtrl.getBudget();
// 3. Display the budget on the UI
UICtrl.displayBudget(budget);
};
var updatePercentages = function() {
// 1. Calculate percentages
budgetCtrl.calculatePercentages();
// 2. Read percentages from the budget controller
var percentages = budgetCtrl.getPercentages();
// 3. Update the UI with the new percentages
UICtrl.displayPercentages(percentages);
};
var ctrlAddItem = function() {
var input, newItem;
// 1. Get the field input data
input = UICtrl.getInput();
if (input.description !== "" && !isNaN(input.value) && input.value > 0) {
// 2. Add the item to the budget controller
newItem = budgetCtrl.addItem(input.type, input.description, input.value);
// 3. Add the item to the UI
UICtrl.addListItem(newItem, input.type);
// 4. Clear the fields
UICtrl.clearFields();
// 5. Calculate and update budget
updateBudget();
// 6. Calculate and update percentages
updatePercentages();
}
};
var ctrlDeleteItem = function(event) {
var itemID, splitID, type, ID;
itemID = event.target.parentNode.parentNode.parentNode.parentNode.id;
if (itemID) {
//inc-1
splitID = itemID.split('-');
type = splitID[0];
ID = parseInt(splitID[1]);
// 1. delete the item from the data structure
budgetCtrl.deleteItem(type, ID);
// 2. Delete the item from the UI
UICtrl.deleteListItem(itemID);
// 3. Update and show the new budget
updateBudget();
// 4. Calculate and update percentages
updatePercentages();
}
};
return {
init: function() {
console.log('App has started');
UICtrl.displayBudget({
budget: 0,
totalIncome: 0,
totalExpenses: 0,
percentage: -1
});
setupEventListeners();
}
};
})(budgetController, UIController);
controller.init();
/**********************************************
*** GENERAL
**********************************************/
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.clearfix::after {
content: "";
display: table;
clear: both;
}
body {
color: #555;
font-family: Open Sans;
font-size: 16px;
position: relative;
height: 100vh;
font-weight: 400;
}
.right {
float: right;
}
.red {
color: #FF5049 !important;
}
.red-focus:focus {
border: 1px solid #FF5049 !important;
}
/**********************************************
*** TOP PART
**********************************************/
.top {
height: 40vh;
background-image: linear-gradient(rgba(0, 0, 0, 0.35), rgba(0, 0, 0, 0.35)), url(back.png);
background-size: cover;
background-position: center;
position: relative;
}
.budget {
position: absolute;
width: 350px;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
color: #fff;
}
.budget__title {
font-size: 18px;
text-align: center;
margin-bottom: 10px;
font-weight: 300;
}
.budget__value {
font-weight: 300;
font-size: 46px;
text-align: center;
margin-bottom: 25px;
letter-spacing: 2px;
}
.budget__income,
.budget__expenses {
padding: 12px;
text-transform: uppercase;
}
.budget__income {
margin-bottom: 10px;
background-color: #28B9B5;
}
.budget__expenses {
background-color: #FF5049;
}
.budget__income--text,
.budget__expenses--text {
float: left;
font-size: 13px;
color: #444;
margin-top: 2px;
}
.budget__income--value,
.budget__expenses--value {
letter-spacing: 1px;
float: left;
}
.budget__income--percentage,
.budget__expenses--percentage {
float: left;
width: 34px;
font-size: 11px;
padding: 3px 0;
margin-left: 10px;
}
.budget__expenses--percentage {
background-color: rgba(255, 255, 255, 0.2);
text-align: center;
border-radius: 3px;
}
/**********************************************
*** BOTTOM PART
**********************************************/
/***** FORM *****/
.add {
padding: 14px;
border-bottom: 1px solid #e7e7e7;
background-color: #f7f7f7;
}
.add__container {
margin: 0 auto;
text-align: center;
}
.add__type {
width: 55px;
border: 1px solid #e7e7e7;
height: 44px;
font-size: 18px;
color: inherit;
background-color: #fff;
margin-right: 10px;
font-weight: 300;
transition: border 0.3s;
}
.add__description,
.add__value {
border: 1px solid #e7e7e7;
background-color: #fff;
color: inherit;
font-family: inherit;
font-size: 14px;
padding: 12px 15px;
margin-right: 10px;
border-radius: 5px;
transition: border 0.3s;
}
.add__description {
width: 400px;
}
.add__value {
width: 100px;
}
.add__btn {
font-size: 35px;
background: none;
border: none;
color: #28B9B5;
cursor: pointer;
display: inline-block;
vertical-align: middle;
line-height: 1.1;
margin-left: 10px;
}
.add__btn:active {
transform: translateY(2px);
}
.add__type:focus,
.add__description:focus,
.add__value:focus {
outline: none;
border: 1px solid #28B9B5;
}
.add__btn:focus {
outline: none;
}
/***** LISTS *****/
.container {
width: 1000px;
margin: 60px auto;
}
.income {
float: left;
width: 475px;
margin-right: 50px;
}
.expenses {
float: left;
width: 475px;
}
h2 {
text-transform: uppercase;
font-size: 18px;
font-weight: 400;
margin-bottom: 15px;
}
.icome__title {
color: #28B9B5;
}
.expenses__title {
color: #FF5049;
}
.item {
padding: 13px;
border-bottom: 1px solid #e7e7e7;
}
.item:first-child {
border-top: 1px solid #e7e7e7;
}
.item:nth-child(even) {
background-color: #f7f7f7;
}
.item__description {
float: left;
}
.item__value {
float: left;
transition: transform 0.3s;
}
.item__percentage {
float: left;
margin-left: 20px;
transition: transform 0.3s;
font-size: 11px;
background-color: #FFDAD9;
padding: 3px;
border-radius: 3px;
width: 32px;
text-align: center;
}
.income .item__value,
.income .item__delete--btn {
color: #28B9B5;
}
.expenses .item__value,
.expenses .item__percentage,
.expenses .item__delete--btn {
color: #FF5049;
}
.item__delete {
float: left;
}
.item__delete--btn {
font-size: 22px;
background: none;
border: none;
cursor: pointer;
display: inline-block;
vertical-align: middle;
line-height: 1;
display: none;
}
.item__delete--btn:focus {
outline: none;
}
.item__delete--btn:active {
transform: translateY(2px);
}
.item:hover .item__delete--btn {
display: block;
}
.item:hover .item__value {
transform: translateX(-20px);
}
.item:hover .item__percentage {
transform: translateX(-20px);
}
.unpaid {
background-color: #FFDAD9 !important;
cursor: pointer;
color: #FF5049;
}
.unpaid .item__percentage {
box-shadow: 0 2px 6px 0 rgba(0, 0, 0, 0.1);
}
.unpaid:hover .item__description {
font-weight: 900;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link href="https://fonts.googleapis.com/css?family=Open+Sans:100,300,400,600" rel="stylesheet" type="text/css">
<link href="http://code.ionicframework.com/ionicons/2.0.1/css/ionicons.min.css" rel="stylesheet" type="text/css">
<link type="text/css" rel="stylesheet" href="style.css">
<title>Budgety</title>
</head>
<body>
<div class="top">
<div class="budget">
<div class="budget__title">
Available Budget in <span class="budget__title--month">%Month%</span>:
</div>
<div class="budget__value">+ 2,345.64</div>
<div class="budget__income clearfix">
<div class="budget__income--text">Income</div>
<div class="right">
<div class="budget__income--value">+ 4,300.00</div>
<div class="budget__income--percentage"> </div>
</div>
</div>
<div class="budget__expenses clearfix">
<div class="budget__expenses--text">Expenses</div>
<div class="right clearfix">
<div class="budget__expenses--value">- 1,954.36</div>
<div class="budget__expenses--percentage">45%</div>
</div>
</div>
</div>
</div>
<div class="bottom">
<div class="add">
<div class="add__container">
<select class="add__type">
<option value="inc" selected>+</option>
<option value="exp">-</option>
</select>
<input type="text" class="add__description" placeholder="Add description">
<input type="number" class="add__value" placeholder="Value">
<button class="add__btn"><i class="ion-ios-checkmark-outline"></i></button>
</div>
</div>
<div class="container clearfix">
<div class="income">
<h2 class="icome__title">Income</h2>
<div class="income__list">
<!--
<div class="item clearfix" id="income-0">
<div class="item__description">Salary</div>
<div class="right clearfix">
<div class="item__value">+ 2,100.00</div>
<div class="item__delete">
<button class="item__delete--btn"><i class="ion-ios-close-outline"></i></button>
</div>
</div>
</div>
<div class="item clearfix" id="income-1">
<div class="item__description">Sold car</div>
<div class="right clearfix">
<div class="item__value">+ 1,500.00</div>
<div class="item__delete">
<button class="item__delete--btn"><i class="ion-ios-close-outline"></i></button>
</div>
</div>
</div>
-->
</div>
</div>
<div class="expenses">
<h2 class="expenses__title">Expenses</h2>
<div class="expenses__list">
<!--
<div class="item clearfix" id="expense-0">
<div class="item__description">Apartment rent</div>
<div class="right clearfix">
<div class="item__value">- 900.00</div>
<div class="item__percentage">21%</div>
<div class="item__delete">
<button class="item__delete--btn"><i class="ion-ios-close-outline"></i></button>
</div>
</div>
</div>
<div class="item clearfix" id="expense-1">
<div class="item__description">Grocery shopping</div>
<div class="right clearfix">
<div class="item__value">- 435.28</div>
<div class="item__percentage">10%</div>
<div class="item__delete">
<button class="item__delete--btn"><i class="ion-ios-close-outline"></i></button>
</div>
</div>
</div>
-->
</div>
</div>
</div>
</div>
<script src="app.js"></script>
</body>
</html>
The problem is that in the function formatNumber, the value num is not initialized at first time. For solving this, you can put a default value when the value of num is empty, like this:
var formatNumber = function(num = 0, type = '') {
var numSplit, int, dec, type;
/* + or - befofe a number
on 2 decimals
comma seperating thousands
*/
num = Math.abs(num);
num = num.toFixed(2);
numSplit = num.split('.');
int = numSplit[0];
if (int.length > 3) {
int = int.substr(0, int.length - 3) + ',' + int.substr(int.length - 3, 3); //input 23510, output 23,510
}
dec = numSplit[1];
return (type === 'exp' ? '-' : '+') + ' ' + int + '.' + dec;
};
By clicking button all values are showing properly but when I use key event i.e ENTER Key on textarea to send the data then it's not showing the data. I have tried below code but it's just showing empty div. here is the jsfiddle Link
var messages = document.getElementById("messages");
var textbox = document.getElementById("textbox");
var button = document.getElementById("button");
$(document).ready(function() {
$("#textbox").emojioneArea({
pickerPosition: "top",
events: {
keyup: function(editor, event) {
if (event.which == 13) {
if (event.shiftKey) {
// With shift
} else {
event.preventDefault();
$('#button').click();
}
}
}
}
});
});
button.addEventListener("click", function(event) {
var newMessage = document.createElement("div");
newMessage.setAttribute('class', 'list');
newMessage.innerHTML = textbox.value;
messages.appendChild(newMessage);
textbox.value = "";
});
.wrap {
width: 300px;
margin: 0 auto;
}
.chat-area {
width: 300px;
border: 2px solid #283747;
margin: 0 auto;
height: 200px;
overflow: auto;
}
.title {
background-color: #5D6D7E;
color: #fff;
font-family: verdana;
text-align: center;
padding: 20px 0;
}
.list {
background-color: #34495E;
color: #fff;
font-family: verdana;
list-style-type: none;
padding: 20px 15px 20px 15px;
margin: 10px 10px;
border-radius: 5px;
white-space: pre-wrap;
}
#textbox {
width: 300px;
height: 80px;
font-family: cursive;
}
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/emojionearea/3.4.1/emojionearea.min.css">
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/emojionearea/3.4.1/emojionearea.min.js"></script>
<div class="wrap">
<div class="chat-area">
<div class="title">Chat Box</div>
<div id="messages"></div>
</div>
<textarea id="textbox" type="text" placeholder="shout"></textarea>
</div>
<button id="button">send</button>
Since you are using emojioneArea you should use getText() and setText() methods which comes with emojioneArea library.
Here is a fiddle: https://jsfiddle.net/2vdeLgph/
function sendMessage() {
var newMessage = document.createElement("div");
newMessage.setAttribute('class', 'list');
newMessage.innerHTML = $('#textbox').data("emojioneArea").getText().trim();
messages.appendChild(newMessage);
$('#textbox').data("emojioneArea").setText('');
}