Javascript let user choose element - javascript

https://gyazo.com/aa49eb6d6849b3adabb8924aa9e40594
I have the elements in the diagram and I want to let the user choose in which element they are going to add the semi column to add text, but I dont know how to let them select a element and then add according to that selection.
var addDetail = document.getElementById('addDetail');
var clauseInput = document.getElementsByClassName('clause');
document.addEventListener('click', function(e) {
e = e || window.event;
var target = e.target || e.srcElement;
if(target == clauseInput[0] || target == clauseInput[1] ||
target == clauseInput[2] || target == clauseInput[3] ||
target == clauseInput[4] || target == addDetail) {
document.getElementById('addDetail').style.display='inline-block';
// createDetail();
console.log(target);
} else {
document.getElementById('addDetail').style.display='none';
}
}, false);

Update
Instead of searching through all clause elements every time when addDetail been clicked, there is e.relatedTarget that really suitable to your problem, detailed documentation, and the update snippet :
/*CREATE TOP AND BOTTOM CLAUSES*/
/*Top Clauses*/
const addClauseTop = document.querySelector('#addClauseTop');
var targetClauseElement;
var addDetail = document.getElementById('addDetail');
addDetail.addEventListener('focusin', function(e) {
createDetail(e.relatedTarget);
});
window.addEventListener('mouseup',function(e) {
if ( e.currentTarget != addDetail ) {
addDetail.style.display='none';
}
});
var firstTopClause = document.getElementsByClassName('clause')[0];
firstTopClause.addEventListener('click', function(e) {
addDetail.style.display='inline-block';
});
var firstBottomClause = document.getElementsByClassName('clauseDivReverse')[0];
firstBottomClause.addEventListener('click', function(e) {
addDetail.style.display='inline-block';
});
addClauseTop.addEventListener('click',function(e){
e.preventDefault();
//Get Divs-Overlay
const topDivs = document.querySelector('#topClauses');
const bottomDivs = document.querySelector('#bottomClauses');
// Create Elements
const clauseDiv = document.createElement('div');
const clauseText = document.createElement('input');
const clauseStroke = document.createElement('div');
// // //Give Style
clauseDiv.classList.add('clauseDiv');
clauseDiv.addEventListener('click', function(e) {
addDetail.style.display='inline-block';
});
clauseText.classList.add('clause');
clauseText.setAttribute("id", "clause");
clauseStroke.classList.add('strokeClause');
//
// // Append to document
clauseDiv.appendChild(clauseText);
clauseDiv.appendChild(clauseStroke);
topDivs.appendChild(clauseDiv);
document.body.appendChild(topDivs);
document.body.appendChild(bottomDivs);
})
/*BOTTOM Clauses*/
const addClauseBottom = document.querySelector('#addClauseBottom');
addClauseBottom.addEventListener('click',function(e){
e.preventDefault();
//Get Divs-Overlay
const topDivs = document.querySelector('#topClauses');
const bottomDivs = document.querySelector('#bottomClauses');
// Create Elements
const clauseDiv = document.createElement('div');
clauseDiv.addEventListener('click', function(e) {
targetClauseElement = e.currentTarget;
addDetail.style.display='inline-block';
});
const clauseText = document.createElement('input');
const clauseStroke = document.createElement('div');
// // //Give Style
clauseDiv.classList.add('clauseDivReverse');
clauseText.classList.add('clauseReverse');
clauseText.setAttribute("id", "clauseReverse");
clauseStroke.classList.add('strokeClauseReverse');
//
// // Append to document
clauseDiv.appendChild(clauseText);
clauseDiv.appendChild(clauseStroke);
bottomDivs.appendChild(clauseDiv);
document.body.appendChild(bottomDivs);
})
/***********/
//Create a addDetail
function createDetail(target){
var mainColumn = target.parentElement;
var strokeColumn = mainColumn.children[1];
// Create Elements
var levelOneDiv = document.createElement('div');
var levelOneText = document.createElement('input');
if ( mainColumn.classList.contains('clauseDiv') ) {
levelOneDiv.classList.add('levelOneClauseReverse');
levelOneText.classList.add('levelOneTextReverse');
//I thought you have not completed your style yet, like something levelOneClause class
} else {
levelOneDiv.classList.add('levelOneClauseReverse');
levelOneText.classList.add('levelOneTextReverse');
}
levelOneDiv.appendChild(levelOneText);
strokeColumn.appendChild(levelOneDiv);
}
#import url('https://fonts.googleapis.com/css?family=Vollkorn+SC');
body{
margin: 10%;
margin-right: 15%;
margin-left: 10%;
margin-top: 5%;
}
h1{
color: #3B3C3D;
font-family: 'Vollkorn SC', serif;
font-size: 2em;
text-align:center;
}
h2{
color: #3B3C3D;
font-family: 'Vollkorn SC', serif;
font-size: 1.5em;
text-align:center;
}
#bottomClauses{
clear: both;
float: right;
}
/*CONTROL-PANEL*/
#controlPanel{
float: inline-block;
margin-top: 5%;
margin-left: 20%;
margin-right: 20%;
margin-bottom: 15%;
padding-bottom: 2%;
border-radius: 10%;
border-bottom: 0.1vw solid #3B3C3D;
}
.addClause{
background-color: #2c3e50;
margin-top: 5%;
font-size: 0.75em;
padding: 0.5em;
border: 0;
color: #FFF;
}
.addClause:hover{
cursor: pointer;
background-color: #000;
}
.addDetail{
display: none;
background-color: #2c3e50;
margin-top: 5%;
font-size: 0.75em;
padding: 0.5em;
border: 0;
color: #FFF;
}
.addDetail:hover{
cursor: pointer;
background-color: #000;
}
/*FISHBONE*/
#fishBone{
position: relative;
float:right;
top: 19.75vw;
width: 100%;
height: 0.2vw;
background-color: #34495e;
}
#finalResult{
position: absolute;
/*float:right;*/
left: 83.5vw;
top: 44.25vw;
width: 7.5vw;
height: 7.5vw;
padding: 1vw;
text-align: center;
color: #FFF;
background-color: #7f8c8d;
border-radius: 50%;
border: 0.15vw solid #34495e;
}
/*NEW CLAUSE*/
.clauseDiv{
display: inline-block;
float:right;
width: 5vw;
margin-right: 12.5vw;
}
.clause{
float: inline-block;
position: relative;
top: -3.5vw;
right: 2vw;
text-align: center;
width: 5.8vw;
height: 1.5vw;
padding: 0.2vw;
color: #FFF;
background-color: #3498db;
border-radius: 0.15vw;
border: 0;
}
.strokeClause{
position: relative;
top: -5.75vw;
transform: rotate(-25deg);
background-color: #34495e;
width: 0.1vw;
height: 25vw;
margin-left: 7.5vw;
border: 0.05vw solid #34495e;
border-radius: 0.1vw;
float: inline-block;
z-index: -1;
}
/*NEW CLAUSE REVERSE*/
.clauseDivReverse{
float: inline-block;
float:right;
width: 5vw;
margin-right: 12.5vw;
}
.clauseReverse{
position: relative;
top: 15.5vw;
right: 2.5vw;
float: inline-block;
text-align: center;
width: 5.8vw;
height: 1.5vw;
padding: 0.2vw;
color: #FFF;
background-color: #3498db;
border-radius: 0.15vw;
border: 0;
}
.strokeClauseReverse{
position: relative;
top: -9.75vw;
transform: rotate(25deg);
background-color: #34495e;
width: 0.1vw;
height: 25vw;
margin-left: 7.5vw;
border: 0.05vw solid #34495e;
border-radius: 0.1vw;
float: inline-block;
z-index: -1;
}
/*NEW LEVEL ONE*/
.levelOneClauseReverse{
margin-bottom: 5vw;
}
.levelOneTextReverse{
border: 0;
position: relative;
font-size: 0.75vw;
width: 13vw;
top: 4.5vw;
right: 12.75vw;
border-bottom: 0.1vw solid #34495e;
transform: rotate(-25deg);
}
<body>
<h1>Diagram Editor</h1>
<div id='controlPanel'>
<h2>Control Panel</h2>
<input type='submit' name='addClause' value='Clause on TOP' class='addClause' id='addClauseTop'>
<input type='submit' name='addClause' value='Clause on BOTTOM' class='addClause' id='addClauseBottom'>
<input type='submit' name='addClause' value='Add Detail' class='addDetail' id='addDetail'>
</div>
<div id='fishBone'></div>
<input type='text' name='clause' id='finalResult'>
<div id='topClauses'>
<div class='clauseDiv'>
<input class='clause' id='clause'>
<div class='strokeClause'>
</div>
</div>
</div>
<div id='bottomClauses'>
<div class='clauseDivReverse' >
<input class='clauseReverse clause'>
<div class='strokeClauseReverse'>
<div class='levelOneClauseReverse'>
<input class='levelOneTextReverse'>
</div>
<div class='levelOneClauseReverse'>
<input class='levelOneTextReverse'>
</div>
<div class='levelOneClauseReverse'>
<input class='levelOneTextReverse'>
</div>
<div class='levelOneClauseReverse'>
<input class='levelOneTextReverse'>
</div>
</div>
</div>
</div>
<script src="app.js"></script>
</body>

Related

Get substring from url and copy to clip board?

Hey i am trying some thing for my school project, i hope you can help me in it.
I want to copy the substring from url, like
Url = https://www.example.com/blah/blah&code=12432
substring = 12432
Also i want to print the substring in Copy Box .
Please Help Me with this issue. It is required for my project to copy some text from string.
(function() {
var copyButton = document.querySelector('.copy button');
var copyInput = document.querySelector('.copy input');
copyButton.addEventListener('click', function(e) {
e.preventDefault();
var text = copyInput.select();
document.execCommand('copy');
});
copyInput.addEventListener('click', function() {
this.select();
});
})();
html, body {
height: 100%;
}
body {
font-size: 16px;
background: #FFD1DD;
display: flex;
align-items: center;
justify-content: center;
}
* {
box-sizing: border-box;
}
.wrapper {
padding: 0 5px;
}
h1 {
text-align: center;
font-size: 40px;
margin-bottom: 1.2em;
text-decoration: underline;
text-transform: uppercase;
}
p {
font-family: 'VT323', monospace;
font-size: 20px;
}
.container {
display: flex;
background: #FFA3BB;
border-radius: 7px;
padding: 10px;
margin: 0 auto;
}
h3 {
font-size: 28px;
text-transform: uppercase;
text-align: center;
span {
display: inline-block;
position: relative;
}
}
.copy, .paste {
flex-grow: 1;
width: 50%;
}
.copy {
border-right: 2px solid;
padding-right: 10px;
h3 {
span {
background: #76ECFF;
}
}
input {
padding-right: 90px;
}
}
.paste {
padding-left: 10px;
h3 {
span {
background: #FAE916;
}
}
}
form {
position: relative;
width: 100%;
input {
display: block;
width: 100%;
border: 3px solid;
outline: 0;
background: #FFF;
font-size: 25px;
padding: 5px 4px;
margin-bottom: 20px;
}
button {
display: block;
position: absolute;
top: 50%;
right: 10px;
transform: translateY(-50%);
border: 0;
outline: 0;
color: #FFF;
background: #000;
font-family: 'VT323', monospace;
font-size: 25px;
text-transform: uppercase;
padding: 0.08em 0.8em;
cursor: pointer;
}
}
<div class="wrapper">
<h1>Link Copy</h1>
<p>Select the link text by clicking within the input then copy yourself or just click the copy button. Paste into the paste side to see that it works!</p>
<div class="container">
<div class="copy">
<h3>Copy <span><i class="fa fa-hand-peace-o"></i></span></h3>
<form>
<input type="text" value="https://codepen.io/she_codes/pen/OgrJJe/">
<button type="button">Copy</button>
</form>
</div>
<div class="paste">
<h3>Paste <span><i class="fa fa-smile-o"></i></span></h3>
<form>
<input type="text">
</form>
</div>
</div><!-- end .container -->
</div><!-- end .wrapper -->
Use this it will work
const params = new Proxy(new URLSearchParams(window.location.search), {
get: (searchParams, prop) => searchParams.get(prop),
});
// Get the value of "some_key" in eg "https://example.com/?some_key=some_value"
let value = params.some_key; // "some_value"
try this, assuming nothing is ever after "code="
var url = window.location.href;
var index = url.indexOf("code=");
var substring = url.substring(index + 5);
copyInput.setAttribute('value', substring);

Reverse() is not working and so does unshift() in vanilla javascript

The issue is only there when I'm trying to reverse the user input, reverse() is returning the string as it is and so does the unshift().
what I'm looking for is if the user enters input - 1234 the output should be 4,3,2,1, but I'm getting is output - 1,2,3,4.
const pahere = [];
const revephare = [];
let donereve = [];
let dff = document.getElementById("Udt1");
function tex(){
if(dff. value == "") {
console.log("enter text")
}
else {
pahere.push(dff.value);
console.log(dff.value);
console.log(pahere);
console.log(pahere.length);
for(let i = 0; i < pahere.length; i++){
revephare.push(pahere[i].split(""));
pahere.pop();
}
}
console.log("I should be splited",revephare);
donereve = revephare.reverse();
console.log("I should be reversed",donereve);
}
* {
box-sizing: border-box;
}
body{
background: #333;
margin: 0;
}
h1{
margin: 15px;
color: white;
}
.holder{
margin-left: 12px;
width: 34em;
height: 37em;
border: 2px solid rgba(255, 51, 153,1);
display: flex;
}
#Udt1 {
width: 56%;
height: 2em!important;
text-align: center;
}
span {
color: white;
margin-top: 5px;
}
.anshold {
width: 154px;
height: 34px;
margin-left: 43em;
position: relative;
top: -592px !important;
border: 2px solid rgba(255, 51, 153,1);
text-align: center;
}
#udans{
color: white;
text-align: center;
margin: 0;
padding: 4px;
}
.btn {
width: 16%;
height: 2em!important;
text-align: center;
margin-left: 14px;
}
<body>
<h1>Palidrom Checker</h1>
<div class="holder">
<span>Word goes here-</span>
<input type="text" name="textin" label ="textin" id="Udt1" placeholder="Eg-Racecar">
<button class="btn" onclick="tex()"> Check</button>
</div>
<div class="anshold"><p id="udans"> </p>
</div>
</body>
Your trying to spliting Array pahere[i].split("")
const pahere = [];
const revephare = [];
let donereve = [];
let dff = document.getElementById("Udt1");
function tex(){
if(dff. value == "") {
console.log("enter text")
}
else {
pahere.push(dff.value);
console.log(dff.value);
console.log(pahere);
console.log(pahere.length);
for(let i = 0; i <dff.value.length; i++){
revephare.push(dff.value[i]);
pahere.pop();
}
}
console.log("I should be splited",revephare);
donereve = revephare.reverse();
console.log("I should be reversed",donereve);
}
* {
box-sizing: border-box;
}
body{
background: #333;
margin: 0;
}
h1{
margin: 15px;
color: white;
}
.holder{
margin-left: 12px;
width: 34em;
height: 37em;
border: 2px solid rgba(255, 51, 153,1);
display: flex;
}
#Udt1 {
width: 56%;
height: 2em!important;
text-align: center;
}
span {
color: white;
margin-top: 5px;
}
.anshold {
width: 154px;
height: 34px;
margin-left: 43em;
position: relative;
top: -592px !important;
border: 2px solid rgba(255, 51, 153,1);
text-align: center;
}
#udans{
color: white;
text-align: center;
margin: 0;
padding: 4px;
}
.btn {
width: 16%;
height: 2em!important;
text-align: center;
margin-left: 14px;
}
<body>
<h1>Palidrom Checker</h1>
<div class="holder">
<span>Word goes here-</span>
<input type="text" name="textin" label ="textin" id="Udt1" placeholder="Eg-Racecar">
<button class="btn" onclick="tex()"> Check</button>
</div>
<div class="anshold"><p id="udans"> </p>
</div>
</body>
This is because you're using Array.prototype.push incorrectly which gives you an array of arrays as a result
revephare.push(pahere[i].split("")); // this line is incorrect
Replace it by the following to make it work
// use spread operator to pass each element as a separate argument
revephare.push(...pahere[i].split(""));
Hi i know you fixed the issue, you can achieve your output by this single line code, just try if you can
let reversed=(pahere.toString()).split("").map(Number).reverse();

How to make modal window accurately reflect contents of each note in a note-taking app?

I am fairly new to javascript, and am working on a note-taking app to practice some things I have learned so far. It all works fine, however, when I click on the Read More button to view overflow text of the note, it displays the text from the most recent note, as opposed to the note I click Read More on. I want the entire text of a particular note to be displayed when its corresponding Read More button is pressed. Am I overthinking this? I think some kind of implementation of for...of, or for loops may help me achieve this outcome. This is a link to my codepen: https://codepen.io/oliverc96/pen/xxdZYrr
const addNote = document.querySelector('.add-note');
const newNote = document.querySelector('#new-note');
const noteFeed = document.querySelector('#note-feed');
let modalBg = document.createElement('div');
let modalWindow = document.createElement('div');
let exitSymbol = document.createElement('i');
let modalText = document.createElement('p');
function expandNote() {
modalWindow.classList.add('enterAnimation');
modalBg.style.visibility = 'visible';
exitSymbol.addEventListener('click', () => {
modalBg.style.visibility = 'hidden';
modalWindow.classList.remove('enterAnimation');
})
}
function createNote() {
const noteContainer = document.createElement('div');
noteContainer.classList.add('containerStyle');
let noteHeader = document.createElement('h1');
const noteNum = noteFeed.childElementCount;
noteHeader.innerText = `Note #${noteNum + 1}`;
noteHeader.classList.add('headerStyle');
noteContainer.append(noteHeader);
let noteText = document.createElement('p');
noteText.innerText = `${newNote.value}`;
noteText.classList.add('paraStyle');
noteContainer.append(noteText);
let readMore = document.createElement('button');
readMore.innerText = 'Read More';
readMore.classList.add('btnStyle');
noteContainer.append(readMore);
noteFeed.append(noteContainer);
readMore.addEventListener('click', expandNote);
modalBg.classList.add('modal-bg');
modalWindow.classList.add('modal-window');
exitSymbol.className = 'far fa-times-circle';
exitSymbol.classList.add('exitSymbol');
modalWindow.append(exitSymbol);
modalText.classList.add('fullTextStyle');
modalText.innerText = `${noteText.innerText}`;
modalWindow.append(modalText);
modalBg.append(modalWindow);
noteContainer.append(modalBg);
newNote.value = '';
}
addNote.addEventListener('click', createNote);
newNote.addEventListener('keyup', function(e) {
if (e.keyCode === 13) {
e.preventDefault();
createNote();
}
})
Actually your modalText will always store the latest value according to your code. You can follow the following steps to solve this.
Attach an data-attribute to that noteText.
When click on read more pass the id of that specific note.
Now just show the innerText of that selected item. You can use querySelector to get the element using data-attribute.
You can check my implementation.
console.clear();
const addNote = document.querySelector('.add-note');
const newNote = document.querySelector('#new-note');
const noteFeed = document.querySelector('#note-feed');
let modalBg = document.createElement('div');
let modalWindow = document.createElement('div');
let exitSymbol = document.createElement('i');
let modalText = document.createElement('p');
function expandNote(noteContainer, noteNum) {
return function () {
modalWindow.classList.add('enterAnimation');
modalBg.style.visibility = 'visible';
exitSymbol.addEventListener('click', () => {
modalBg.style.visibility = 'hidden';
modalWindow.classList.remove('enterAnimation');
})
const data = document.querySelector(`[data-id='${noteNum}']`).innerText;
showMoreModal(noteContainer, data);
}
}
function showMoreModal(noteContainer, data) {
modalBg.classList.add('modal-bg');
modalWindow.classList.add('modal-window');
exitSymbol.className = 'far fa-times-circle';
exitSymbol.classList.add('exitSymbol');
modalWindow.append(exitSymbol);
modalText.classList.add('fullTextStyle');
modalText.innerText = `${data}`;
modalWindow.append(modalText);
modalBg.append(modalWindow);
noteContainer.append(modalBg);
}
function createNote() {
const noteContainer = document.createElement('div');
noteContainer.classList.add('containerStyle');
let noteHeader = document.createElement('h1');
const noteNum = noteFeed.childElementCount;
noteHeader.innerText = `Note #${noteNum + 1}`;
noteHeader.classList.add('headerStyle');
noteContainer.append(noteHeader);
let noteText = document.createElement('p');
noteText.innerText = `${newNote.value}`;
noteText.classList.add('paraStyle');
noteText.setAttribute('data-id', noteNum);
noteContainer.append(noteText);
let readMore = document.createElement('button');
readMore.innerText = 'Read More';
readMore.classList.add('btnStyle');
noteContainer.append(readMore);
noteFeed.append(noteContainer);
readMore.addEventListener('click', expandNote(noteContainer, noteNum));
newNote.value = '';
}
addNote.addEventListener('click', createNote);
newNote.addEventListener('keyup', function(e) {
if (e.keyCode === 13) {
e.preventDefault();
createNote();
}
})
* {
padding: 0;
margin: 0;
box-sizing: border-box;
font-family: 'Montserrat', sans-serif;
}
#wrapper {
width: 1600px;
height: 100vh;
margin: auto;
text-align: center;
}
h1 {
font-size: 100px;
margin-top: 20px;
font-weight: 500;
}
h2 {
font-size: 50px;
font-weight: 400;
margin-top: 10px;
}
#add-new-note {
color: rgb(0, 153, 153);
}
textarea {
width: 1500px;
margin-top: 30px;
height: 60px;
border-radius: 6px;
padding: 20px;
font-size: 18px;
}
textarea:focus {
outline-color: black;
}
.add-note {
font-size: 20px;
width: 180px;
height: 50px;
border-radius: 6px;
margin-top: 30px;
background-color: rgb(0, 153, 153);
color: white;
border-style: solid;
border-color: rgb(0, 102, 102);
}
.add-note:hover {
background-color: rgb(0, 128, 128);
cursor: pointer;
}
#note-feed {
background-color: rgb(0, 153, 153);
height: 500px;
margin-top: 25px;
width: 1500px;
border-radius: 6px;
display: flex;
overflow: scroll;
flex-wrap: wrap;
padding: 20px 10px;
margin-left: 50px;
}
.containerStyle {
display: flex;
flex-direction: column;
justify-content: space-around;
background-color: rgb(169, 169, 214);
height: 48%;
width: 31%;
margin-right: 11px;
margin-left: 20px;
border-radius: 6px;
margin-bottom: 20px;
overflow: hidden;
padding: 0 28px;
padding-bottom: 15px;
text-align: left;
}
.headerStyle {
font-size: 30px;
}
.paraStyle {
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
font-size: 18px;
text-overflow: ellipsis;
overflow: hidden;
}
.btnStyle {
font-size: 20px;
width: 150px;
height: 40px;
border-radius: 6px;
background-color: rgb(255, 128, 128);
color: white;
border-style: solid;
border-color: rgb(255, 77, 77);
align-self: left;
}
.btnStyle:hover {
background-color: rgb(255, 102, 102);
cursor: pointer;
}
.modal-bg {
z-index: 1;
position: fixed;
width: 100%;
height: 100%;
top: 0;
left: 0;
background: rgba(0,0,0,0.5);
color: white;
display: flex;
justify-content: center;
align-items: center;
visibility: hidden;
overflow: scroll;
}
.modal-window {
border-radius: 6px;
background: white;
width: 70%;
min-height: 30%;
max-height: 70%;
overflow: scroll;
display: flex;
justify-content: flex-start;
align-items: flex-start;
}
.enterAnimation {
animation-name: fadeInDown;
animation-duration: 1s;
}
#keyframes fadeInDown {
0% {
opacity: 0;
transform: translateY(-200px);
}
100% {
opacity: 1;
}
}
.exitSymbol {
color: rgb(0, 128, 128);
font-size: 30px;
margin: 20px 20px;
}
.exitSymbol:hover {
cursor: pointer;
opacity: 0.8;
}
.fullTextStyle {
color: black;
width: 90%;
height: 80%;
text-align: left;
margin-top: 60px;
margin-bottom: 30px;
font-size: 18px;
}
<html>
<head>
<title> Note Taker </title>
<link type="text/css" href="notes.css" rel="stylesheet">
<link href="https://fonts.googleapis.com/css2?family=Montserrat:wght#100;200;300;400;500;600;700&display=swap" rel="stylesheet">
</head>
<body>
<div id="wrapper">
<h1> Note Taker </h1>
<h2 id="add-new-note"> Add A New Note: </h2>
<textarea id="new-note" name="note-box" placeholder="Write your note here"></textarea>
<button class="add-note"> Add Note </button>
<div id="note-feed">
</div>
</div>
<script src="notes.js"></script>
<script src="https://kit.fontawesome.com/6fc6f370ca.js" crossorigin="anonymous"></script>
</body>
</html>

Strange behavior while adding DOM element using addEventListener() on a button

I'm trying to create a project card with user info when the user clicks on a button. When the user clicks the new project button, a modal form pops up that takes the user info and has a create button. The program should add a new project card whenever the user clicks the create button. To achieve this I added a click event listener to the Add new project button and another to Create button. I nested the create event listener inside the add new project event listener.
Here's the event listener.
addTileBtn.addEventListener("click", (e) => {
e.preventDefault();
modal.style.display = "block";
const titleField = document.querySelector("#title");
const descriptionField = document.querySelector("#description");
const create = document.querySelector("#create");
const close = document.querySelector("#close");
create.addEventListener("click", (e) => {
e.preventDefault();
title = titleField.value;
description = descriptionField.value;
function createProjectTile() {
const projectTile = document.createElement("div");
projectTile.classList.add("cards-grid__tile");
projectTile.textContent = title;
console.log(title, description);
return projectTile;
}
cardsGrid.appendChild(createProjectTile());
modal.style.display = "none";
});
close.addEventListener("click", (e) => {
e.preventDefault();
modal.style.display = "none";
});
});
The problem is that when I create the first card it works fine. But the second time, it creates two cards and 3 cards on the 3rd time and so on.
Here is the JSFiddle link for the full code.
I've edited your code, this should be what you wanted:
const logoutBtn = document.querySelector("#logout");
const addTileBtn = document.querySelector("#add-tile");
const cardsGrid = document.querySelector(".cards-grid");
const modal = document.querySelector(".modal");
const titleField = document.querySelector("#title");
const descriptionField = document.querySelector("#description");
const create = document.querySelector("#create");
const close = document.querySelector("#close");
addTileBtn.addEventListener("click", (e) => {
e.preventDefault();
modal.style.display = "block";
titleField.value = "";
descriptionField.value = "";
});
create.addEventListener("click", (e) => {
e.preventDefault();
title = titleField.value;
description = descriptionField.value;
function createProjectTile() {
const projectTile = document.createElement("div");
projectTile.classList.add("cards-grid__tile");
projectTile.textContent = title;
console.log(title, description);
return projectTile;
}
cardsGrid.appendChild(createProjectTile());
modal.style.display = "none";
});
close.addEventListener("click", (e) => {
e.preventDefault();
modal.style.display = "none";
});
:root {
--main-red: #be3144;
--main-white: #f0f0f0;
--main-gray: #303841;
--main-blue: #45567d;
--main-blue3: #1c262f;
--main-blue2: #27333d;
--main-blue1: #2e3d49;
--main-light-blue: #02b3e4;
--main-black: #000000;
--main-light-black: #3a3d40;
--main-dark-black: #181719;
}
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
html,
body {
height: 100%;
}
img {
display: block;
max-width: 100%;
height: auto;
}
body {
font-family: "Poppins", sans-serif;
font-size: 1.8rem;
font-weight: 400;
line-height: 1.4;
color: var(--main-white);
}
h1,
h2 {
font-family: "Raleway", sans-serif;
font-weight: 700;
text-align: center;
}
h1 {
font-size: 3.5rem;
}
h2 {
font-size: 2rem;
color: var(--main-blue);
display: block;
}
p {
font-size: 1.8rem;
font-weight: 200;
font-style: italic;
color: var(--main-white);
}
a {
text-decoration: none;
text-align: center;
display: block;
}
.main {
display: flex;
flex-direction: row;
justify-content: space-between;
height: 100vh;
background-color: var(--main-white);
}
.box {
border: none;
box-shadow: 0 2px 4px rgb(0 0 0 / 10%), 0 8px 16px rgb(0 0 0 / 10%);
border-radius: 8px;
background-color: #fff;
}
.box__fields {
padding: 20px;
}
.box-field {
margin-bottom: 20px;
display: flex;
justify-content: center;
}
.icon {
position: absolute;
padding: 10px;
color: gray;
min-width: 50px;
text-align: center;
font-size: 20px;
top: 50%;
transform: translateY(-50%);
}
input,
textarea {
font-size: 17px;
padding: 14px 16px;
width: 300px;
cursor: text;
border: 1px solid var(--main-gray);
border-radius: 6px;
outline: none;
padding-left: 45px;
}
.box-btn {
border: none;
border-radius: 6px;
font-size: 20px;
line-height: 48px;
padding: 0 16px;
}
.app,
.main-content {
height: 100%;
}
.title-area {
background-color: var(--main-blue3);
width: 100%;
font-size: 18px;
min-height: 60px;
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: space-between;
align-items: center;
position: fixed;
top: 0;
left: 0;
}
.title-area__item {
padding: 10px 30px;
}
.logout-btn {
border: none;
border-radius: 6px;
font-size: 20px;
line-height: 30px;
padding: 0 16px;
width: 100px;
cursor: pointer;
color: #fff;
background-color: var(--main-light-blue);
}
.logout-btn:hover {
background-color: #029be4;
}
.content-area {
margin-top: 60px;
width: 100%;
height: 100%;
overflow: auto;
background-color: var(--main-blue);
}
.cards-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
grid-gap: 50px;
margin-bottom: 3rem;
padding: 5rem 3rem;
}
.cards-grid__tile {
background-color: var(--main-blue2);
max-width: 200px;
padding: 30px;
text-align: center;
font-size: 1.2rem;
}
.add-tile-btn {
border: none;
border-radius: 6px;
font-size: 15px;
line-height: 48px;
padding: 0 10px;
cursor: pointer;
color: #fff;
background-color: var(--main-light-blue);
}
.modal {
display: none;
width: 350px;
font-size: 1.2rem;
position: relative;
top: 10%;
left: 50%;
transform: translateX(-50%);
overflow: visible;
}
.box {
background-color: var(--main-blue1);
opacity: 0.95;
}
.box-field {
flex-direction: column;
}
input,
textarea {
padding: 5px 10px;
resize: none;
}
.wrapper {
position: relative;
text-align: center;
}
.create-btn {
width: 100px;
cursor: pointer;
color: #fff;
background-color: var(--main-light-blue);
}
.close {
cursor: pointer;
position: absolute;
top: 20px;
left: 290px;
}
#modal-form {
position: absolute;
}
.icon {
color: var(--main-blue3);
}
<div class="app">
<div class="nav-wrapper">
<nav id="nav" class="nav"></nav>
</div>
<div class="main-content">
<div class="title-area">
<div class="title-area__item">Menu</div>
<div class="title-area__item">Boards</div>
<div class="title-area__item">
<button id="logout" class="logout-btn btn">
Logout
</button>
</div>
</div>
<div class="content-area">
<div class="modal">
<form id="modal-form" class="box">
<a id="close" class="close">
<i class="fa fa-times icon">close</i>
</a>
<div class="box__fields">
<div class="box-field">
<label for="title"> Title </label>
<input
id="title"
type="text"
name="title"
required
autofocus
/>
</div>
<div class="box-field">
<label for="description">
Description
</label>
<textarea
id="description"
name="title"
rows="6"
cols="40"
></textarea>
</div>
<div class="box-field">
<div class="wrapper">
<button
id="create"
class="create-btn box-btn btn"
>
Create
</button>
</div>
</div>
</div>
</form>
</div>
<div class="cards-grid">
<div class="cards-grid__tile">
<button id="add-tile" class="add-tile-btn btn">
+ Add new project
</button>
</div>
</div>
</div>
</div>
</div>

How to stop password field from showing 'null' as a placeholder?

I have a password field which is interactive and has some js going on behind the scenes. However I have this issue of when I click on the field, it shows 'null' as a value, as per the image.
This only shows when I click on the field, and I have no placeholder given to the input either. How do I prevent this from showing?
The code
//floating input controller
const FloatLabel = (() => {
// add active class
const handleFocus = (e) => {
const target = e.target;
target.parentNode.classList.add('active');
target.setAttribute('placeholder', target.getAttribute('data-placeholder'));
};
// remove active class
const handleBlur = (e) => {
const target = e.target;
if (!target.value) {
target.parentNode.classList.remove('active');
}
target.removeAttribute('placeholder');
};
// register events
const bindEvents = (element) => {
const floatField = element.querySelector('input');
floatField.addEventListener('focus', handleFocus);
floatField.addEventListener('blur', handleBlur);
};
// get DOM elements
const init = () => {
const floatContainers = document.querySelectorAll('.float-container');
floatContainers.forEach((element) => {
if (element.querySelector('input').value) {
element.classList.add('active');
}
bindEvents(element);
});
};
return {
init: init
};
})();
FloatLabel.init();
.float-container {
position: relative;
background-color: #dfecff;
width: 100%;
border-radius: 5px;
transition: 150ms;
padding-top: .6em;
padding-bottom: .6em;
border: 2px solid #b9d6ff;
}
.float-container:hover {
background-color: #1a73e8;
cursor: text;
}
.password-toggle-button {
position: absolute;
font-size: 1em;
padding-top: 8px;
color: #333333;
margin-left: 93%;
}
.password-toggle-button:hover {
cursor: pointer;
color: #eeeeee;
}
label {
font-size: 1em;
font-family: Arial, Helvetica, sans-serif;
color: #5e5e5e;
position: absolute;
margin-left: 3%;
z-index: 140;
transform: translate(0, 0) scale(1);
pointer-events: none;
user-select: none;
transform-origin: top left;
transition: all .1s ease-in-out;
}
.float-container input {
color: #eeeeee;
}
.float-container.active label {
transform: translate(-0.5em, -1.5em) scale(.95);
font-style: italic;
font-weight: 200;
border-radius: 10px;
background-color: #1a73e8;
padding-left: .5em;
padding-right: .5em;
color: #eeeeee;
}
.float-container.active input {
color: #eeeeee;
}
.float-container.active {
background-color: #1a73e8;
border: 2px solid #eeeeee;
}
.form-center {
display: relative;
margin-top: 3em;
margin-left: 5vw;
margin-bottom: 5em;
word-break: break-all;
padding-top: 3%;
padding-left: 5vw;
padding-right: 3vw;
padding-bottom: 5%;
width: 60vw;
line-height: 2em;
background-color: #1a73e8;
border-radius: 20px;
border-width: 3px;
border-style: solid;
border-color: #333333;
}
input{
border: none;
background-color: transparent;
color: #333333;
outline: 0;
margin-top: auto;
margin-left: 3%;
margin-right: 20%;
width: 90%;
z-index: 150;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.12.0-2/css/all.min.css" rel="stylesheet" />
<div class="form-center"><div id="float-container" class="float-container" onclick="document.getElementById('pw').focus(); return false;">
<label for="pw" class="inner-label">Password</label>
<i class="fa fa-eye password-toggle-button" aria-hidden="true"></i>
<input type="password" class="floatField id="pw" placeholder="">
</div>
</div>
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.12.0-2/css/all.min.css" rel="stylesheet" />
<div class="form-center"><div id="float-container" class="float-container" onclick="document.getElementById('pw').focus(); return false;">
<label for="pw" class="inner-label">Password</label>
<i class="fa fa-eye password-toggle-button" aria-hidden="true"></i>
<input type="password" class="floatField id="pw">
</div>
</div>
Have you tried removing the placeholder?
You have to verify if the value is null before setting it as the input placeholder:
const handleFocus = (e) => {
const target = e.target;
target.parentNode.classList.add('active');
const placeholder = target.getAttribute('data-placeholder');
if (!!placeholder && placeholder !== 'null') {
target.setAttribute('placeholder', placeholder);
} else {
// Do something else
}
};

Categories