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
}
};
Related
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);
// GET
const getAdviceNumber = document.querySelector('#adviceNumber');
const adviceResultsDiv = document.querySelector('#adviceResults');
const diceBtn = document.querySelector('#spinDice');
const staticText = document.querySelector('#static');
const favouriteSection = document.querySelector('.favouriteSection')
diceBtn.addEventListener('click', () => {
const getAPI = async () => {
// Call API
/* eslint-disable */
const res = await axios.get('https://api.adviceslip.com/advice');
// remove static text
staticText.remove();
// Generate spin on btn
const element = document.querySelector('#spinDice');
element.classList.add('rotateMe');
setTimeout(() => element.classList.remove('rotateMe'), 800);
// generate unique id number
const header = document.createElement('h1');
header.className = 'title';
header.append(` ADVICE # ${res.data.slip.id}`);
while (getAdviceNumber.childElementCount > 0) {
getAdviceNumber.firstChild.remove();
}
getAdviceNumber.append(header);
// generate unique advice
const para = document.createElement('p');
para.className = 'para';
para.append(`"${res.data.slip.advice}"`);
while (adviceResultsDiv.childElementCount > 0) {
adviceResultsDiv.firstChild.remove();
}
adviceResultsDiv.append(para);
//generate add to favourites button
const addFavourite = document.createElement('p');
addFavourite.className = 'fav';
addFavourite.innerHTML = `<p>Add to Favourites<i class="fa-solid fa-folder-plus"></i></p>`;
while (favouriteSection.childElementCount > 0) {
favouriteSection.firstChild.remove();
}
favouriteSection.append(addFavourite)
};
getAPI();
favouriteSection.addEventListener('click', () => {
const favouriteItem = document.createElement('p');
favouriteItem.innerHTML = `<p class="icons"><i class="fa-solid fa-magnifying-glass"></i> <i class="fa-solid fa-trash-can"></i></p>`
favouriteItem.className = 'favouriteItemBorder';
favouriteSection.append(favouriteItem)
favouriteItem.append(`${getAdviceNumber.textContent}: ${ adviceResultsDiv.textContent}`)
})
});
body {
background-color: hsl(218, 23%, 16%);
font-family: Arial, Helvetica, sans-serif;
}
#advice-container {
background-color: hsl(217, 19%, 38%);
border-radius: 20px;
position: absolute;
-ms-transform: translateY(-50%);
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 300px;
padding-bottom: 40px;
}
h2 {
color: hsl(193, 38%, 86%);
text-align: center;
}
.title {
color: hsl(150, 100%, 66%);
font-size: 15px;
text-align: center;
margin-top: 20px;
}
.para {
color: hsl(193, 38%, 86%);
font-size: 28px;
font-weight: 500;
text-align: center;
margin: 20px 20px 0 20px;
}
.btn {
margin-top: 40px;
margin-bottom: -75px;
}
.dice-container {
background-color: hsl(150, 100%, 66%);
border: solid 2px hsl(193, 38%, 86%);
border-radius: 33px;
margin: 20px 110px 0 110px;
}
.dice-container:hover {
box-shadow: 0 0 30px -2px #52ffa8;
}
.fa-dice-five {
font-size: 50px;
width: 100%;
text-align: center;
padding-top: 10px;
padding-bottom: 10px;
padding-right: 10px;
/* transform: rotate(90deg); */
}
.rotate {
transition: all 0s ease;
transform: rotate(0deg);
}
.rotateMe {
transition: all 0.3s ease;
transform: rotate(90deg);
}
#icons {
color: hsl(193, 38%, 86%);
}
.icon-container {
padding: 20px 120px 0 120px;
width: 100%;
}
.fa-grip-lines-vertical {
margin: 0 10px 0 10px;
}
.line {
width: 100%;
}
.favouriteSection {
position: absolute;
top: 70%;
}
.fav {
color: #52ffa8;
font-size: 32px;
margin: 20px;
}
.fa-folder-plus {
margin-left: 10px;
}
.favouriteItemBorder {
border: 2px solid white;
width: 300px;
height: 60px;
margin: 20px;
padding: 10px;
text-align: center;
}
.icons {
position:absolute;
bottom:10px;
left: 40%;
font-size: 20px;
}
/* desktop ..................................................................................... */
#media screen and (min-width: 720px) {
#advice-container {
display: flex;
width: 900px;
flex-direction: column;
justify-content: space-between;
align-items: center;
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <!-- displays site properly based on user's device -->
<title>Oshane| Advice generator app</title>
<link rel="stylesheet" href="style.css">
<script src="https://kit.fontawesome.com/030a66e167.js" crossorigin="anonymous"></script>
</head>
<body>
<section id="advice-container">
<div id="static">
<h2>Click the Dice Button <br><br> below <br><br> to get advice</h2>
</div>
<div id="adviceNumber"> </div>
<div id="adviceResults"></div>
<div class="btn" id="getDataBtn">
<button id="spinDice" class="dice-container rotate" type="submit"><i class="fa-solid fa-dice-five"></i></button>
</div>
</section>
<section class="favouriteSection">
</section>
<!-- <script src="./node_modules/axios/dist/axios.min.js"></script> -->
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script src="app.js"></script>
</body>
</html>
]2]2how can I prevent this from adding the same text each time the add favourite icon is clicked? It should just add it once and if the add favourite btn is selected again and the quote already exists it should not repeat adding the same ones. I tried a few stuff but as I am a beginner those did not work.
Please anyone can assist?
You can check for something before adding/pushing into favorites array.
Check if something like id(best) or string exists in the arrray and if so - return, else push
Step by step, this is what you are missing:
Create an empty object.
Each time the user clicks the "Add to Favourites" button, you should check if it's already in that object.
If it is, you are done handling that click event.
If it is not, you should add it to the object and then proceed with the logic you currently have to update the UI.
Simplified example:
const rollButton = document.getElementById('roll');
const numberElement = document.getElementById('number');
const addToFavouritesButton = document.getElementById('addToFavourites');
const favouritesElement = document.getElementById('favourites');
let number = null;
rollButton.addEventListener('click', () => {
numberElement.textContent = number = Math.floor(Math.random() * 10);
addToFavouritesButton.removeAttribute('disabled');
});
const favourites = {};
addToFavouritesButton.addEventListener('click', () => {
if (favourites[number]) return;
favourites[number] = true;
favouritesElement.textContent = Object.keys(favourites).sort((a, b) => a - b).join(', ');
if (Object.keys(favourites).length === 10) {
numberElement.textContent = '🎉';
rollButton.setAttribute('disabled', true);
addToFavouritesButton.setAttribute('disabled', true);
}
});
body,
button {
font-family: monospace;
}
p {
text-align: center;
}
button {
border: 3px solid black;
border-radius: 4px;
background: transparent;
padding: 8px 16px;
}
button:hover {
background: yellow;
}
button:disabled {
border-color: #CCC;
color: #CCC;
background: transparent;
}
#number {
border: 3px solid black;
width: 48px;
height: 48px;
display: inline-flex;
align-items: center;
justify-content: center;
border-radius: 4px;
}
#favourites {
display: inline-flex;
align-items: center;
justify-content: center;
border: 3px solid black;
border-radius: 4px;
background: transparent;
padding: 8px 16px;
}
<p>
<button id="roll">🎲 Roll Dice</button>
<button id="addToFavourites" disabled>⭐ Add to Favourites</button>
</p>
<p>
<span id="number">?</span>
</p>
<p>
<span id="favourites"> </span>
</p>
I began to change the copied code, so that instead of it being a "to-do" list that shoots out one statement at a time, I wanted to change it to shoot out 3 statements at a time and log them in a row.
I was able to add 2 more boxes, but when I press the purple button to have it run, it logs only one of the boxes and it leaves writing in the other 2 (new boxes I made) and it ends up looking like this before pressing the purple button:
enter image description here
and this logs out as a result :
enter image description here
just the name, but email does not and it leaves an imprint of the email and date (unlike the 'user name box')
Tried tinkering with eth code but don't understand how to manipulate it to make it show what I want and log the three things. Can you please help show me how to do this. Below are 3 files for HTML, CSS, and JS.
// getting all required elements
const inputBox = document.querySelector(".inputField input");
const addBtn = document.querySelector(".inputField button");
const todoList = document.querySelector(".todoList");
const deleteAllBtn = document.querySelector(".footer button");
// onkeyup event
inputBox.onkeyup = ()=>{
let userEnteredValue = inputBox.value; //getting user entered value
if(userEnteredValue.trim() != 0){ //if the user value isn't only spaces
addBtn.classList.add("active"); //active the add button
}else{
addBtn.classList.remove("active"); //unactive the add button
}
}
showTasks(); //calling showTask function
addBtn.onclick = ()=>{ //when user click on plus icon button
let userEnteredValue = inputBox.value; //getting input field value
let getLocalStorageData = localStorage.getItem("New Todo"); //getting localstorage
if(getLocalStorageData == null){ //if localstorage has no data
listArray = []; //create a blank array
}else{
listArray = JSON.parse(getLocalStorageData); //transforming json string into a js object
}
listArray.push(userEnteredValue); //pushing or adding new value in array
localStorage.setItem("New Todo", JSON.stringify(listArray)); //transforming js object into a json string
showTasks(); //calling showTask function
addBtn.classList.remove("active"); //unactive the add button once the task added
}
function showTasks(){
let getLocalStorageData = localStorage.getItem("New Todo");
if(getLocalStorageData == null){
listArray = [];
}else{
listArray = JSON.parse(getLocalStorageData);
}
const pendingTasksNumb = document.querySelector(".pendingTasks");
pendingTasksNumb.textContent = listArray.length; //passing the array length in pendingtask
if(listArray.length > 0){ //if array length is greater than 0
deleteAllBtn.classList.add("active"); //active the delete button
}else{
deleteAllBtn.classList.remove("active"); //unactive the delete button
}
let newLiTag = "";
listArray.forEach((element, index) => {
newLiTag += `<li>${element}<span class="icon" onclick="deleteTask(${index})"><i class="fas fa-trash"></i></span></li>`;
});
todoList.innerHTML = newLiTag; //adding new li tag inside ul tag
inputBox.value = ""; //once task added leave the input field blank
}
// delete task function
function deleteTask(index){
let getLocalStorageData = localStorage.getItem("New Todo");
listArray = JSON.parse(getLocalStorageData);
listArray.splice(index, 1); //delete or remove the li
localStorage.setItem("New Todo", JSON.stringify(listArray));
showTasks(); //call the showTasks function
}
// delete all tasks function
deleteAllBtn.onclick = ()=>{
listArray = []; //empty the array
localStorage.setItem("New Todo", JSON.stringify(listArray)); //set the item in localstorage
showTasks(); //call the showTasks function
}
#import url('https://fonts.googleapis.com/css2?family=Poppins:wght#200;300;400;500;600;700&display=swap');
*{
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Poppins', sans-serif;
}
::selection{
color: #ffff;
background: rgb(142, 73, 232);
}
body{
width: 100%;
height: 100vh;
/* overflow: hidden; */
padding: 10px;
background: linear-gradient(to bottom, #68EACC 0%, #497BE8 100%);
}
.wrapper{
background: #fff;
max-width: 1200px;
width: 100%;
margin: 120px auto;
padding: 25px;
border-radius: 5px;
box-shadow: 0px 10px 15px rgba(0,0,0,0.1);
}
.wrapper header{
font-size: 30px;
font-weight: 600;
}
.wrapper .inputField{
margin: 20px 0;
width: 100%;
display: flex;
height: 45px;
}
.inputField input{
width: 85%;
height: 100%;
outline: none;
border-radius: 3px;
border: 1px solid #ccc;
font-size: 17px;
padding-left: 15px;
transition: all 0.3s ease;
}
.inputField input:focus{
border-color: #8E49E8;
}
.inputField button{
width: 100px;
height: 100%;
border: none;
color: #fff;
margin-left: 5px;
font-size: 21px;
outline: none;
background: #8E49E8;
cursor: pointer;
border-radius: 3px;
opacity: 0.6;
pointer-events: none;
transition: all 0.3s ease;
}
.inputField button:hover,
.footer button:hover{
background: #721ce3;
}
.inputField button.active{
opacity: 1;
pointer-events: auto;
}
.wrapper .todoList{
max-height: 250px;
overflow-y: auto;
}
.todoList li{
position: relative;
list-style: none;
height: 45px;
line-height: 45px;
margin-bottom: 8px;
background: #f2f2f2;
border-radius: 3px;
padding: 0 15px;
cursor: default;
overflow: hidden;
}
.todoList li .icon{
position: absolute;
right: -45px;
background: #e74c3c;
width: 45px;
text-align: center;
color: #fff;
border-radius: 0 3px 3px 0;
cursor: pointer;
transition: all 0.2s ease;
}
.todoList li:hover .icon{
right: 0px;
}
.wrapper .footer{
display: flex;
width: 100%;
margin-top: 20px;
align-items: center;
justify-content: space-between;
}
.footer button{
padding: 6px 10px;
border-radius: 3px;
border: none;
outline: none;
color: #fff;
font-weight: 400;
font-size: 16px;
margin-left: 5px;
background: #8E49E8;
cursor: pointer;
user-select: none;
opacity: 0.6;
pointer-events: none;
transition: all 0.3s ease;
}
.footer button.active{
opacity: 1;
pointer-events: auto;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>To Do App</title>
<link rel="stylesheet" href="todo.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css"/>
</head>
<body>
<div class="wrapper">
<header>Support Tickets</header>
<div class="inputField" >
<input type="text" placeholder="Users Name" required>
<input type="email" placeholder="Users Email" required>
<input type="text" placeholder="Date" required>
<button><i class="fas fa-plus"></i></button>
</div>
<ul class="todoList">
<!-- data are comes from local storage -->
</ul>
<div class="footer">
<span>You have <span class="pendingTasks"></span> pending tasks</span>
<button>Clear All</button>
</div>
</div>
<script src="todo.js"></script>
</body>
</html>
First of all you never used the value of email and date and hence only the name was being displayed.
I made a few changes to your listArray structure and made it an object, something like this
let userEnteredValue = {
name: inputBox.value,
email: email.value,
date: date.value
};
for better understanding and code readability.
Then I made a few changes to your css to to display it in a line.
Also i added a button in place of trash can icon because, I don't have bootstrap but you can replace the button with the icon again
const inputBox = document.querySelector(".inputField input");
const email = document.querySelector("#email");
const date = document.querySelector("#date");
const addBtn = document.querySelector(".inputField button");
const todoList = document.querySelector(".todoList");
const deleteAllBtn = document.querySelector(".footer button");
// onkeyup event
inputBox.onkeyup = () => {
let userEnteredValue = inputBox.value; //getting user entered value
if (userEnteredValue.trim() != 0) {
//if the user value isn't only spaces
addBtn.classList.add("active"); //active the add button
} else {
addBtn.classList.remove("active"); //unactive the add button
}
};
showTasks(); //calling showTask function
addBtn.onclick = () => {
//when user click on plus icon button
let userEnteredValue = {
name: inputBox.value,
email: email.value,
date: date.value,
}; //getting input field value
console.log(userEnteredValue);
let getLocalStorageData = localStorage.getItem("New Todo"); //getting localstorage
if (getLocalStorageData == null) {
//if localstorage has no data
listArray = []; //create a blank array
} else {
listArray = JSON.parse(getLocalStorageData); //transforming json string into a js object
}
listArray.push(userEnteredValue); //pushing or adding new value in array
localStorage.setItem("New Todo", JSON.stringify(listArray)); //transforming js object into a json string
showTasks(); //calling showTask function
addBtn.classList.remove("active"); //unactive the add button once the task added
};
function showTasks() {
todoList.innerHTML = "";
let getLocalStorageData = localStorage.getItem("New Todo");
if (getLocalStorageData == null) {
listArray = [];
} else {
listArray = JSON.parse(getLocalStorageData);
}
const pendingTasksNumb = document.querySelector(".pendingTasks");
pendingTasksNumb.textContent = listArray.length; //passing the array length in pendingtask
if (listArray.length > 0) {
//if array length is greater than 0
deleteAllBtn.classList.add("active"); //active the delete button
} else {
deleteAllBtn.classList.remove("active"); //unactive the delete button
}
// console.log(listArray);
listArray.forEach((element, index) => {
let newLiTag = "";
newLiTag = `<li>${element.name} ${element.email} ${element.date}<span class="icon" onclick="deleteTask(${index})"><button>Delete</button></span></li><br>`;
todoList.insertAdjacentHTML("afterbegin", newLiTag); //adding new li tag inside ul tag
});
// console.log(newLiTag);
inputBox.value = "";
email.value = "";
date.value = ""; //once task added leave the input field blank
}
// delete task function
function deleteTask(index) {
let getLocalStorageData = localStorage.getItem("New Todo");
listArray = JSON.parse(getLocalStorageData);
console.log(listArray);
listArray.splice(index, 1); //delete or remove the li
localStorage.setItem("New Todo", JSON.stringify(listArray));
showTasks(); //call the showTasks function
}
// delete all tasks function
deleteAllBtn.onclick = () => {
todoList.innerHTML = "";
listArray = []; //empty the array
localStorage.setItem("New Todo", JSON.stringify(listArray)); //set the item in localstorage
showTasks(); //call the showTasks function
};
#import url("https://fonts.googleapis.com/css2?family=Poppins:wght#200;300;400;500;600;700&display=swap");
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: "Poppins", sans-serif;
}
::selection {
color: #ffff;
background: rgb(142, 73, 232);
}
body {
width: 100%;
height: 100vh;
/* overflow: hidden; */
padding: 10px;
background: linear-gradient(to bottom, #68eacc 0%, #497be8 100%);
}
.wrapper {
background: #fff;
max-width: 1200px;
width: 100%;
margin: 120px auto;
padding: 25px;
border-radius: 5px;
box-shadow: 0px 10px 15px rgba(0, 0, 0, 0.1);
}
.wrapper header {
font-size: 30px;
font-weight: 600;
}
.wrapper .inputField {
margin: 20px 0;
width: 100%;
display: flex;
height: 45px;
}
.inputField input {
width: 85%;
height: 100%;
outline: none;
border-radius: 3px;
border: 1px solid #ccc;
font-size: 17px;
padding-left: 15px;
transition: all 0.3s ease;
}
.inputField input:focus {
border-color: #8e49e8;
}
.inputField button {
width: 100px;
height: 100%;
border: none;
color: #fff;
margin-left: 5px;
font-size: 21px;
outline: none;
background: #8e49e8;
cursor: pointer;
border-radius: 3px;
opacity: 0.6;
pointer-events: none;
transition: all 0.3s ease;
}
.inputField button:hover,
.footer button:hover {
background: #721ce3;
}
.inputField button.active {
opacity: 1;
pointer-events: auto;
}
.wrapper .todoList {
max-height: 250px;
overflow-y: auto;
}
.todoList li {
position: relative;
list-style: none;
height: 45px;
line-height: 45px;
margin-bottom: 8px;
background: #f2f2f2;
border-radius: 3px;
padding: 0 15px;
cursor: default;
overflow: hidden;
}
.todoList li .icon {
position: absolute;
right: -45px;
background: #e74c3c;
width: 45px;
text-align: center;
color: #fff;
border-radius: 0 3px 3px 0;
cursor: pointer;
transition: all 0.2s ease;
}
.todoList li:hover .icon {
right: 20px;
}
.wrapper .footer {
display: flex;
width: 100%;
margin-top: 20px;
align-items: center;
justify-content: space-between;
}
.footer button {
padding: 6px 10px;
border-radius: 3px;
border: none;
outline: none;
color: #fff;
font-weight: 400;
font-size: 16px;
margin-left: 5px;
background: #8e49e8;
cursor: pointer;
user-select: none;
opacity: 0.6;
pointer-events: none;
transition: all 0.3s ease;
}
.footer button.active {
opacity: 1;
pointer-events: auto;
}
.todoList li {
font-size: 25px;
width: 100%;
display: block;
word-spacing: 250px;
}
<div class="wrapper">
<header>Support Tickets</header>
<div class="inputField">
<input type="text" id="name" placeholder="Users Name" required />
<input type="email" id="email" placeholder="Users Email" required />
<input type="text" id="date" placeholder="Date" required />
<button><i class="fas fa-plus"></i></button>
</div>
<ul class="todoList">
<!-- data are comes from local storage -->
</ul>
<div class="footer">
<span>You have <span class="pendingTasks"></span> pending tasks</span>
<button>Clear All</button>
</div>
</div>
Since localStorage won't run in this snippet below is a output screenshot
Now,everyting works just as you want them to!!
Also your code, which I edited needs a lot of refactoring for better readability and efficiency.....
I am creating a little effect with an input, but I am facing a problem.
I have an input and as a placeholder I am using a paragraph which I used translate to position inside the input.
What I am doing is when the input is focused the paragraph is moved up and when it is not focused it is put back in its original position, 'inside' the input.
Like this:
The problem is that in order to make the input focused I have to click on it, but the p is ahead of it, so, when I click on the text I don't reach the input, consequently it doesn't get focused and the p doesn't move.
Is there a way to send the p behind the input? I tried with z-index, but it seems that it doesn't work to inputs.
Is there anything similar that would work?
const placeholder = document.getElementsByClassName('frete-input-placeholder')[0].parentNode.children
const h2 = document.getElementById('h2')
window.addEventListener('click', () => {
if (placeholder[1] === document.activeElement) {
placeholder[0].style.transform = 'translate(0, 30px)'
h2.innerHTML = 'FOCUSED'
} else {
placeholder[0].style.transform = 'translate(0, 55px)'
h2.innerHTML = 'NOT FOCUSED'
}
})
.frete-calculo-cep {
display: flex;
justify-content: space-between;
align-items: flex-end;
width: 65%;
}
.frete-calculo-cep div {
width: 62%;
}
.frete-input-placeholder {
background-color: tomato;
width: 20%;
margin-left: 10px;
transform: translate(0, 55px);
transition: 0.5s;
}
.frete-calculo-cep input {
max-width: 93%;
height: 42px;
outline: none;
border:1px solid #BEBEBE;
padding-left: 10px;
font-size: 18px;
z-index: 9999;
border-radius: 3px;
}
.frete-calculo-cep input:focus {
outline: none;
border:1px solid #5A98FF;
}
.frete-calculo-cep button {
width: 35%;
height: 45px;
background-color: #5F22A8;
color: white;
font-weight: bold;
font-size: 17px;
border: 0;
cursor: pointer;
border-radius: 3px;
}
.frete-calculo-cep button:hover {
background-color: #7032bb;
}
.frete-calculo-cep button:focus {
outline: 0;
}
<div class="frete-calculo-cep">
<div>
<p class="frete-input-placeholder" >Digite seu CEP</p>
<input type="text" />
</div>
</div>
<h2 id="h2">NOT FOCUSED</h2>
Just set pointer-events:none; on the paragraph in CSS.
But also, document.getElementsByClassName()[0] is really, really not good code. Instead use document.querySelector as I've shown below.
And, instead of inline styles, always try to use CSS classes, which you can easily add, remove or toggle with element.classList.
Finally, don't use .innerHTML when there is no HTML in the string you are working with as .innerHTML has security and performance implications. Use textContent instead.
const placeholder = document.querySelector('.frete-input-placeholder');
const input = document.querySelector("input");
const h2 = document.getElementById('h2')
window.addEventListener('click', () => {
if (input === document.activeElement) {
placeholder.classList.add("focused");
h2.textContent = 'FOCUSED'
} else {
placeholder.classList.remove("focused");
h2.textContent = 'NOT FOCUSED'
}
})
.frete-calculo-cep {
display: flex;
justify-content: space-between;
align-items: flex-end;
width: 65%;
}
.frete-calculo-cep div {
width: 62%;
}
.frete-input-placeholder {
background-color: tomato;
width: 20%;
margin-left: 10px;
transform: translate(0, 55px);
transition: 0.5s;
pointer-events:none; /* <---- This is all you need */
}
/* Use CSS Classes instead of inline CSS */
.focused { transform:translate(0, 30px); }
.frete-calculo-cep input {
max-width: 93%;
height: 42px;
outline: none;
border:1px solid #BEBEBE;
padding-left: 10px;
font-size: 18px;
z-index: 9999;
border-radius: 3px;
}
.frete-calculo-cep input:focus {
outline: none;
border:1px solid #5A98FF;
}
.frete-calculo-cep button {
width: 35%;
height: 45px;
background-color: #5F22A8;
color: white;
font-weight: bold;
font-size: 17px;
border: 0;
cursor: pointer;
border-radius: 3px;
}
.frete-calculo-cep button:hover {
background-color: #7032bb;
}
.frete-calculo-cep button:focus {
outline: 0;
}
<div class="frete-calculo-cep">
<div>
<p class="frete-input-placeholder" >Digite seu CEP</p>
<input type="text" />
</div>
</div>
<h2 id="h2">NOT FOCUSED</h2>
I just moved the p behind with position absolute
const placeholder = document.getElementsByClassName('frete-input-placeholder')[0].parentNode.children
const h2 = document.getElementById('h2')
window.addEventListener('click', () => {
if (placeholder[1] === document.activeElement) {
placeholder[0].style.transform = 'translate(0, 30px)'
h2.innerHTML = 'FOCUSED'
} else {
placeholder[0].style.transform = 'translate(0, 55px)'
h2.innerHTML = 'NOT FOCUSED'
}
})
.frete-calculo-cep {
display: flex;
justify-content: space-between;
align-items: flex-end;
width: 65%;
margin-top: 50px;
}
.frete-calculo-cep div {
width: 62%;
}
.frete-input-placeholder {
background-color: tomato;
width: 20%;
margin-left: 10px;
position: absolute;
top: -20px;
transform: translate(0, 55px);
transition: 0.5s;
}
.frete-calculo-cep input {
max-width: 93%;
height: 42px;
outline: none;
border:1px solid #BEBEBE;
padding-left: 10px;
font-size: 18px;
z-index: 9999;
border-radius: 3px;
}
.frete-calculo-cep input:focus {
outline: none;
border:1px solid #5A98FF;
}
.frete-calculo-cep button {
width: 35%;
height: 45px;
background-color: #5F22A8;
color: white;
font-weight: bold;
font-size: 17px;
border: 0;
cursor: pointer;
border-radius: 3px;
}
.frete-calculo-cep button:hover {
background-color: #7032bb;
}
.frete-calculo-cep button:focus {
outline: 0;
}
#input1 {
position: relative;
}
<div class="frete-calculo-cep">
<div>
<p class="frete-input-placeholder" >Digite seu CEP</p>
<input type="text" id="input1" />
</div>
</div>
<h2 id="h2">NOT FOCUSED</h2>
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>