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>
Related
let myLibrary = [
{
id: 0,
title: "The Once and Future King",
author: "White",
pages: 654,
read: false,
},
{
id: 1,
title: "The Hobbit",
author: "Tolkien",
pages: 304,
read: false,
},
];
const bookContent = document.getElementById("content");
function displayBook(book) {
const addBook = document.createElement("div");
addBook.className = "book";
addBook.id = book.id;
bookContent.appendChild(addBook);
addBook.innerHTML = `
<div class="title">
<p class="bookTitle">
<span>${book.title}</span>
</p>
</div>
<div class="body">
<p>
Author: <span>${book.author}</span>
</p>
<p>
Pages: <span>${book.pages}</span>
</p>
</div>
<div class="read">
<label class="switch" data-book="0">
<input type="checkbox" />
<span class="slider round"></span>
</label>
</div>
<div class="delete">
<button class="delete-btn">DELETE</button>
</div>`;
}
// Display your original object list
myLibrary.forEach((book) => {
displayBook(book);
});
// Handle your object creation
const form = document.getElementById("form");
form.addEventListener("submit", updateLibrary);
function updateLibrary(event) {
// Need this so it doesn't refresh page
event.preventDefault();
const title = document.getElementById("title").value;
const author = document.getElementById("author").value;
const pages = document.getElementById("pages").value;
const book = {
title: title,
author: author,
pages: parseInt(pages),
read: false,
};
// Adds object to array
myLibrary.push(book);
// Displays new book
displayBook(book);
// Reset form
resetForm();
// Close form
document.getElementById("addBookForm").style.display = "none";
console.log(myLibrary);
}
// Resets the form so user can input another book
function resetForm() {
document.getElementById("form").reset();
}
// The form is automatically set to hidden. This loads it up for the user
const openForm = function () {
document.getElementById("addBookForm").style.display = "block";
document.getElementById("title").focus();
};
// Sets the form display back to none
const closeForm = () =>
(document.getElementById("addBookForm").style.display = "none");
/* .main {
} */
.header {
display: flex;
flex-direction: column;
background-color: #c689c6;
height: 150px;
border: 1px solid #3b133b;
}
.btn {
margin: 0 auto;
margin-top: 55px;
display: block;
text-align: center;
background-color: #4649ff;
padding: 0.75rem 1.25rem;
border-radius: 10rem;
color: #fff;
cursor: pointer;
font-size: 1rem;
letter-spacing: 0.15rem;
transition: all 0.3s;
}
.btn:hover {
background-color: #3134fa;
}
.content {
display: flex;
flex-flow: row wrap;
align-content: flex-start;
justify-content: flex-start;
background-color: #fffdfa;
height: auto;
}
.book {
border: 2px solid #ffa94d;
background-color: #ffd8a8;
color: #d9480f;
width: 280px;
height: 365px;
margin: 10px;
}
.title {
border-bottom: 2px solid #ffa94d;
}
.title p {
display: flex;
align-items: center;
text-align: center;
justify-content: center;
font-size: larger;
}
.title span {
color: #3c4048;
}
.body {
border: 1px solid transparent;
height: 200px;
background-color: #fff4e6;
}
.body p {
padding-left: 20px;
}
p span {
color: #3c4048;
}
.read {
display: flex;
align-items: center;
justify-content: center;
height: 50px;
border-top: 2px solid #ffa94d;
text-align: center;
}
/* The switch - the box around the slider */
.switch {
position: relative;
display: inline-block;
width: 60px;
height: 34px;
}
/* Hide default HTML checkbox */
.switch input {
opacity: 0;
width: 0;
height: 0;
}
/* The slider */
.slider {
position: absolute;
cursor: pointer;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: #ccc;
-webkit-transition: 0.4s;
transition: 0.4s;
}
.slider:before {
position: absolute;
content: "";
height: 26px;
width: 26px;
left: 4px;
bottom: 4px;
background-color: white;
-webkit-transition: 0.4s;
transition: 0.4s;
}
input:checked + .slider {
background-color: #3d8361;
}
input:focus + .slider {
box-shadow: 0 0 1px #3d8361;
}
input:checked + .slider:before {
-webkit-transform: translateX(26px);
-ms-transform: translateX(26px);
transform: translateX(26px);
}
/* Rounded sliders */
.slider.round {
border-radius: 34px;
}
.slider.round:before {
border-radius: 50%;
}
.delete {
height: 50px;
border-top: 2px solid #ffa94d;
}
.delete-btn {
margin: 0 auto;
margin-top: 8px;
display: block;
text-align: center;
background-color: #e94560;
padding: 0.5rem 0.75rem;
border-radius: 10rem;
color: #fff;
cursor: pointer;
letter-spacing: 0.15rem;
transition: all 0.3s;
}
.delete-btn:hover {
background-color: #e7082d;
}
.close-btn {
color: #e7082d;
font-size: large;
background-color: #c689c6;
border: none;
float: right;
cursor: pointer;
}
/* THE FORM */
.form-content {
display: flex;
justify-content: center;
}
.form {
display: none;
position: fixed;
margin-top: 5px;
border: 2px solid #3b133b;
animation: openForm 0.5s;
z-index: 1;
}
#keyframes openForm {
from {
transform: scale(0);
}
to {
transform: scale(1);
}
}
.form h1 {
text-align: center;
}
.form-container {
background-color: #c689c6;
border: 2px solid black;
max-width: 300px;
padding: 10px;
}
.form-container h1 {
padding-left: 20px;
}
.form-container input[type="text"],
.form-container input[type="number"] {
width: 80%;
padding: 15px;
margin: 5px 0 22px 0;
border: none;
}
.form-container input[type="text"]:focus,
.form-container input[type="number"]:focus {
outline: none;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="styles.css" />
<title>Library</title>
</head>
<body>
<div class="main">
<div class="header">
<button class="btn" id="btn" onclick="openForm()">Add a Book</button>
</div>
<div class="form-content">
<div class="form" id="addBookForm">
<form id="form" action="" class="form-container">
<button type="button" class="close-btn" onclick="closeForm()">
x
</button>
<h1>Add a Book</h1>
<label for="title">Title</label>
<input
type="text"
placeholder="Title"
name="title"
id="title"
required
/>
<label for="author">Author</label>
<input
type="text"
placeholder="Author"
name="author"
id="author"
required
/>
<label for="pages">Pages</label>
<input
type="number"
placeholder="Pages"
name="pages"
required
id="pages"
/>
<button type="submit" id="submit-btn">Submit</button>
</form>
</div>
</div>
<div id="content" class="content"></div>
</div>
</body>
</html>
I have a form where the user inputs information from a book they are reading and upon hitting submit, the information is sent as its own object inside an array. I also have a forEach method running which loops through the array and displays each object as a div on the web page.
let myLibrary = [];
const book = {
title: title,
author: author,
pages: parseInt(pages),
read: false,
};
myLibrary.push(book)
As you can see from the code above, the three properties that the user fills out are the books title, author and page count. There's also a property that is automatically added called the read property and it is automatically set as false.
The Problem
My problem is this. I have the following code displayed at the bottom of each div.
<div class="read">
<label class="switch">
<input type="checkbox" />
<span class="slider round"></span>
</label>
</div>
This code is very simple. It's a toggle switch which I found here.
I want it so when the toggle switch is grayed out, the read status is set to false. But when the toggle switch is turned on, the read property is set to true. I am having a very difficult time figuring out how to get this done.
What I've Tried
I was able to use an onclick to select the toggle switch's parent element, and I tested it using console.log however I am unsure of where to go from there. I attempted to update the book.read to true using the ternary operator but it was out of scope and resulted in an error.
document.querySelector(".main").onclick = (ev) => {
let el = ev.target.classList.contains("switch")
? ev.target.parentElement
: ev.target.classList.contains("slider")
? ev.target
: false;
if (el) {
let toggle = el.parentElement.parentElement.parentElement;
let index = [...toggle.parentElement.children].indexOf(toggle);
myLibrary[index].read = false ? false : true;
console.log(myLibrary[index].read);
}
console.log(myLibrary);
};
Change this
function displayBook(book) {
...
<label class="switch" data-book="0">
to
function displayBook(book,bookIndex) {
...
<label class="switch" data-book="${bookIndex}">
and
myLibrary.forEach((book) => {
displayBook(book);
});
to
myLibrary.forEach((book,i) => {
displayBook(book,i);
});
lastly change
// Displays new book
displayBook(book);
to
// Displays new book
displayBook(book,myLibrary.length-1);
Here is the code inclusive a delete function
It would be slightly simpler if we had an associate array on book_id
Note I removed the numeric ID because it is not needed since the index of the array is the same
let myLibrary = [{
title: "The Once and Future King",
author: "White",
pages: 654,
read: false,
},
{
title: "The Hobbit",
author: "Tolkien",
pages: 304,
read: false,
},
];
const bookContent = document.getElementById("content");
const formDiv = document.getElementById("addBookForm");
function displayBook(book, idx) {
const addBook = document.createElement("div");
addBook.className = "book";
addBook.id = `book_${idx}`;
bookContent.appendChild(addBook);
addBook.innerHTML = `
<div class="title">
<p class="bookTitle">
<span>${book.title}</span>
</p>
</div>
<div class="body">
<p>
Author: <span>${book.author}</span>
</p>
<p>
Pages: <span>${book.pages}</span>
</p>
</div>
<div class="read">
<label class="switch" data-book="${idx}">
<input type="checkbox" />
<span class="slider round"></span>
</label>
</div>
<div class="delete">
<button class="delete-btn">DELETE</button>
</div>`;
}
// Display your original object list
myLibrary.forEach((book, i) => {
displayBook(book, i);
});
const deleteBook = (e) => {
const parent = e.target.closest("div.book");
const idx = parent.querySelector(".switch").dataset.book;
parent.remove();
console.log(idx);
myLibrary.splice(idx, 1);
console.log(myLibrary);
content.querySelectorAll("div.book").forEach((book, i) => { // reset the hard way
book.id = `book_${i}`;
book.querySelector("label.switch").dataset.book = i;
})
};
content.addEventListener("click", function(e) {
const tgt = e.target;
if (!tgt.matches(".delete-btn")) return; // not the delete
deleteBook(e); // pass the event to the delete
})
// Handle your object creation
const form = document.getElementById("form");
form.addEventListener("submit", updateLibrary);
function updateLibrary(event) {
// Need this so it doesn't refresh page
event.preventDefault();
const title = document.getElementById("title").value;
const author = document.getElementById("author").value;
const pages = document.getElementById("pages").value;
const book = {
title: title,
author: author,
pages: parseInt(pages),
read: false,
};
// Adds object to array
myLibrary.push(book);
// Displays new book
displayBook(book);
// Reset form
resetForm();
// Close form
formDiv.style.display = "none";
console.log(myLibrary);
}
// Resets the form so user can input another book
function resetForm() {
document.getElementById("form").reset();
}
// The form is automatically set to hidden. This loads it up for the user
const openForm = function() {
formDiv.style.display = "block";
document.getElementById("title").focus();
};
// Sets the form display back to none
const closeForm = () => formDiv.style.display = "none";
/* .main {
} */
.header {
display: flex;
flex-direction: column;
background-color: #c689c6;
height: 150px;
border: 1px solid #3b133b;
}
.btn {
margin: 0 auto;
margin-top: 55px;
display: block;
text-align: center;
background-color: #4649ff;
padding: 0.75rem 1.25rem;
border-radius: 10rem;
color: #fff;
cursor: pointer;
font-size: 1rem;
letter-spacing: 0.15rem;
transition: all 0.3s;
}
.btn:hover {
background-color: #3134fa;
}
.content {
display: flex;
flex-flow: row wrap;
align-content: flex-start;
justify-content: flex-start;
background-color: #fffdfa;
height: auto;
}
.book {
border: 2px solid #ffa94d;
background-color: #ffd8a8;
color: #d9480f;
width: 280px;
height: 365px;
margin: 10px;
}
.title {
border-bottom: 2px solid #ffa94d;
}
.title p {
display: flex;
align-items: center;
text-align: center;
justify-content: center;
font-size: larger;
}
.title span {
color: #3c4048;
}
.body {
border: 1px solid transparent;
height: 200px;
background-color: #fff4e6;
}
.body p {
padding-left: 20px;
}
p span {
color: #3c4048;
}
.read {
display: flex;
align-items: center;
justify-content: center;
height: 50px;
border-top: 2px solid #ffa94d;
text-align: center;
}
/* The switch - the box around the slider */
.switch {
position: relative;
display: inline-block;
width: 60px;
height: 34px;
}
/* Hide default HTML checkbox */
.switch input {
opacity: 0;
width: 0;
height: 0;
}
/* The slider */
.slider {
position: absolute;
cursor: pointer;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: #ccc;
-webkit-transition: 0.4s;
transition: 0.4s;
}
.slider:before {
position: absolute;
content: "";
height: 26px;
width: 26px;
left: 4px;
bottom: 4px;
background-color: white;
-webkit-transition: 0.4s;
transition: 0.4s;
}
input:checked+.slider {
background-color: #3d8361;
}
input:focus+.slider {
box-shadow: 0 0 1px #3d8361;
}
input:checked+.slider:before {
-webkit-transform: translateX(26px);
-ms-transform: translateX(26px);
transform: translateX(26px);
}
/* Rounded sliders */
.slider.round {
border-radius: 34px;
}
.slider.round:before {
border-radius: 50%;
}
.delete {
height: 50px;
border-top: 2px solid #ffa94d;
}
.delete-btn {
margin: 0 auto;
margin-top: 8px;
display: block;
text-align: center;
background-color: #e94560;
padding: 0.5rem 0.75rem;
border-radius: 10rem;
color: #fff;
cursor: pointer;
letter-spacing: 0.15rem;
transition: all 0.3s;
}
.delete-btn:hover {
background-color: #e7082d;
}
.close-btn {
color: #e7082d;
font-size: large;
background-color: #c689c6;
border: none;
float: right;
cursor: pointer;
}
/* THE FORM */
.form-content {
display: flex;
justify-content: center;
}
.form {
display: none;
position: fixed;
margin-top: 5px;
border: 2px solid #3b133b;
animation: openForm 0.5s;
z-index: 1;
}
#keyframes openForm {
from {
transform: scale(0);
}
to {
transform: scale(1);
}
}
.form h1 {
text-align: center;
}
.form-container {
background-color: #c689c6;
border: 2px solid black;
max-width: 300px;
padding: 10px;
}
.form-container h1 {
padding-left: 20px;
}
.form-container input[type="text"],
.form-container input[type="number"] {
width: 80%;
padding: 15px;
margin: 5px 0 22px 0;
border: none;
}
.form-container input[type="text"]:focus,
.form-container input[type="number"]:focus {
outline: none;
}
<div class="main">
<div class="header">
<button class="btn" id="btn" onclick="openForm()">Add a Book</button>
</div>
<div class="form-content">
<div class="form" id="addBookForm">
<form id="form" action="" class="form-container">
<button type="button" class="close-btn" onclick="closeForm()">
x
</button>
<h1>Add a Book</h1>
<label for="title">Title</label>
<input type="text" placeholder="Title" name="title" id="title" required />
<label for="author">Author</label>
<input type="text" placeholder="Author" name="author" id="author" required />
<label for="pages">Pages</label>
<input type="number" placeholder="Pages" name="pages" required id="pages" />
<button type="submit" id="submit-btn">Submit</button>
</form>
</div>
</div>
<div id="content" class="content"></div>
</div>
I am catching a click and according to click close the menu :
To catch the click the code I tried is :
function someFnc(e){
let currentTarget = menuContain.contains(e.target);
if(!currentTarget){
document.body.style.color = "red";
} else {
document.body.style.color = "blue";
}
}
Other code I tried is :
function someFnc(e){
if(e.target.contains(menuContain)){
document.body.style.color = "red";
} else {
document.body.style.color = "blue";
}
}
Both works the same can anyone tell the reason because I am using same function .contains.
One is checking click is inside menu or not and in other menu is catching click inside it or not
let menuToggleCheck = document.getElementById("menuTogglerCheckbox");
let menuFixBg = document.getElementById("menuFix");
let menu = document.getElementById("menuToggler");
menuToggleCheck.addEventListener('click', menuTogglerBackground)
function menuTogglerBackground() {
if (menuToggleCheck.checked) {
menuFixBg.style.backgroundColor = "rgba(126, 125, 125, 0.5)";
menuFixBg.style.width = "100vw";
menuFixBg.style.height = "100vh";
} else {
menuFixBg.style.backgroundColor = "transparent";
menuFixBg.style.width = "0vw"
menuFixBg.style.height = "0vh"
}
}
let menuContain = document.getElementById("menuContainer");
menuFixBg.addEventListener('click', function(e) {
let currentTarget = menuContain.contains(e.target);
// e.target.contains(menuContain)
if (!currentTarget) {
document.body.style.color = "red";
menuToggleCheck.checked = false;
menuTogglerBackground();
} else {
document.body.style.color = "blue";
}
})
* {
box-sizing: border-box;
}
body {
margin: 0px;
}
#menuFix {
position: fixed;
top: 0px;
}
#menuContainer {
width: 100px;
height: 100vh;
}
#menuToggler {
position: relative;
display: flex;
width: 90px;
height: 80px;
/* left: -100px; */
user-select: none;
}
#menuToggler input {
cursor: pointer;
position: absolute;
width: 40px;
height: 40px;
top: 7px;
left: 21px;
opacity: 0;
z-index: 2;
}
.menuBarCircle {
position: relative;
width: 40px;
height: 40px;
margin-top: 10px;
margin-left: auto;
margin-right: auto;
border: 1px solid black;
border-radius: 20px;
}
#menuToggler span {
position: relative;
display: block;
width: 26px;
height: 3px;
top: 10px;
left: 6px;
margin-bottom: 5px;
border-radius: 5px;
background: black;
transform-origin: 0px 0px;
transition: 0.2s;
z-index: 1;
}
#menuToggler span:nth-child(1) {
background: brown;
transform-origin: 0 0;
}
#menuToggler span:nth-child(3) {
background: brown;
transform-origin: 0 100%;
}
#menuToggler input:checked~.menuBarCircle span {
margin-left: 4px;
}
#menuToggler input:checked~.menuBarCircle span:nth-child(1) {
transform: rotate(45deg) translate(0px, -1px);
}
#menuToggler input:checked~.menuBarCircle span:nth-child(3) {
transform: rotate(-45deg) translate(0, 1px);
}
#menuToggler input:checked~.menuBarCircle span:nth-child(2) {
opacity: 0;
}
#menu {
position: absolute;
list-style-type: none;
width: 90px;
height: 100vh;
margin-top: auto;
padding: 50px 0;
background: white;
border-right: 1px solid black;
/* z-index: -1; */
transform: translate(-100%, 0);
transition: 0.5s width;
}
#menu a {
display: flex;
flex-flow: column;
text-decoration: none;
font-size: 14px;
width: 100%;
padding: 5px 10px;
margin: 5px 0;
color: black;
border: 2px solid white;
border-radius: 20px 0 0 20px;
}
#menu a li {
display: flex;
justify-content: center;
align-items: center;
}
#menu a:hover {
background: rgb(255, 155, 155);
border: 2px solid rgb(255, 155, 155);
}
#menuToggler input:checked~#menu {
display: block;
width: 180px;
transform: translate(0%, 0);
}
#menuToggler input:checked~#menu a {
display: flex;
flex-flow: row;
font-size: 18px;
}
<div id="menuFix">
<div id="menuContainer">
<div id="menuToggler">
<input type="checkbox" id="menuTogglerCheckbox" />
<div class="menuBarCircle">
<span></span>
<span></span>
<span></span>
</div>
<ul id="menu">
<a href="#">
<li>Home</li>
</a>
<a href="#">
<li>Settings</li>
</a>
<a href="#">
<li>About Us</li>
</a>
<a href="#">
<li>Help</li>
</a>
</ul>
</div>
</div>
</div>
<div>Hello World I am with you this is the grace of God to be with you</div>
Although both could have the same effect depending on the HTML structure, they both do not work the same.
And in your provided example, they both do not always have the same result.
firstNode.contains( secondNode ) checks to see if secondNode is a descendant of firstNode and returns this as a boolean value.
It will also return true if a node performs this check on itself; this firstNode.contains( firstNode ) will equate to true.
function someFnc(e){
let currentTarget = menuContain.contains(e.target);
if(!currentTarget){
document.body.style.color = "red";
} else {
document.body.style.color = "blue";
}
}
In the above example, currentTarget holds the answer to the question; "Is e.target a descendant of menuContain".
function someFnc(e){
if(e.target.contains(menuContain)){
document.body.style.color = "red";
} else {
document.body.style.color = "blue";
}
}
In this above code block, you check to see if menuContain is a descendant of e.target.
e.target being the node on which the event was dispatched, or in your code's case, the node that was clicked on.
You can find more information on what .contains() does on this page, and more information on what event.target is on this page.
As for why both appear to work the same on your current code ( but remember, they don't ), well...
let menuContain = document.getElementById("menuContainer");
menuFixBg.addEventListener('click', function(e) {
let currentTarget = menuContain.contains(e.target);
// e.target.contains(menuContain)
if (!currentTarget) {
document.body.style.color = "red";
menuToggleCheck.checked = false;
menuTogglerBackground();
} else {
document.body.style.color = "blue";
}
})
In the above code, in your current HTML structure, #menuContainer occupies all of #menuFix's space, so any click event dispatched from #menuFix will come from either #menuContainer or one of it's descendants.
Because e.target will always either be #menuContainer or one of it's descendants, let currentTarget = menuContain.contains(e.target); will always be true.
Meaning that the font color will turn to blue in any case, with the above code.
In the case of using if ( e.target.contains(menuContain) ) {, this will be different.
If the click event is dispatched from #menuContainer, the if statement will equate to true, but if it's dispatched from one of its descendants, it will equate to false.
This is because descendants of #menuContainer won't contain #menuContainer.
Meaning, depending on where you click, the font will either be red or blue. I would suggest trying out Inspect Element in a browser that supports it and hovering over #menuContainer and its descendants in the Elements list to see what element occupies what space as this will be highlighted on the page.
See the below snippet as an example of how if ( e.target.contains(menuContain) ) { will have differing results depending on where you click.
Clicking near the circle will dispatch a click event from #menuToggler or one of its descendants, meaning the if statement will equate to false and the text will be blue.
Clicking further down, away from the circle, will dispatch a click event from #menuContainer, meaning the if statement will equate to true and the text will be red.
let menuToggleCheck = document.getElementById("menuTogglerCheckbox");
let menuFixBg = document.getElementById("menuFix");
let menu = document.getElementById("menuToggler");
menuToggleCheck.addEventListener('click', menuTogglerBackground)
function menuTogglerBackground() {
if (menuToggleCheck.checked) {
menuFixBg.style.backgroundColor = "rgba(126, 125, 125, 0.5)";
menuFixBg.style.width = "100vw";
menuFixBg.style.height = "100vh";
} else {
menuFixBg.style.backgroundColor = "transparent";
menuFixBg.style.width = "0vw"
menuFixBg.style.height = "0vh"
}
}
let menuContain = document.getElementById("menuContainer");
menuFixBg.addEventListener('click', function(e) {
if ( e.target.contains(menuContain) ) {
// #menuContainer was a descendant of the Clicked Element
// Or the Clicked Element actually was #menuContainer
document.body.style.color = "red";
menuToggleCheck.checked = false;
menuTogglerBackground();
} else {
// #menuContainer was not a descendant of the Clicked Element
document.body.style.color = "blue";
}
})
* {
box-sizing: border-box;
}
body {
margin: 0px;
}
#menuFix {
position: fixed;
top: 0px;
}
#menuContainer {
width: 100px;
height: 100vh;
}
#menuToggler {
position: relative;
display: flex;
width: 90px;
height: 80px;
/* left: -100px; */
user-select: none;
}
#menuToggler input {
cursor: pointer;
position: absolute;
width: 40px;
height: 40px;
top: 7px;
left: 21px;
opacity: 0;
z-index: 2;
}
.menuBarCircle {
position: relative;
width: 40px;
height: 40px;
margin-top: 10px;
margin-left: auto;
margin-right: auto;
border: 1px solid black;
border-radius: 20px;
}
#menuToggler span {
position: relative;
display: block;
width: 26px;
height: 3px;
top: 10px;
left: 6px;
margin-bottom: 5px;
border-radius: 5px;
background: black;
transform-origin: 0px 0px;
transition: 0.2s;
z-index: 1;
}
#menuToggler span:nth-child(1) {
background: brown;
transform-origin: 0 0;
}
#menuToggler span:nth-child(3) {
background: brown;
transform-origin: 0 100%;
}
#menuToggler input:checked~.menuBarCircle span {
margin-left: 4px;
}
#menuToggler input:checked~.menuBarCircle span:nth-child(1) {
transform: rotate(45deg) translate(0px, -1px);
}
#menuToggler input:checked~.menuBarCircle span:nth-child(3) {
transform: rotate(-45deg) translate(0, 1px);
}
#menuToggler input:checked~.menuBarCircle span:nth-child(2) {
opacity: 0;
}
#menu {
position: absolute;
list-style-type: none;
width: 90px;
height: 100vh;
margin-top: auto;
padding: 50px 0;
background: white;
border-right: 1px solid black;
/* z-index: -1; */
transform: translate(-100%, 0);
transition: 0.5s width;
}
#menu a {
display: flex;
flex-flow: column;
text-decoration: none;
font-size: 14px;
width: 100%;
padding: 5px 10px;
margin: 5px 0;
color: black;
border: 2px solid white;
border-radius: 20px 0 0 20px;
}
#menu a li {
display: flex;
justify-content: center;
align-items: center;
}
#menu a:hover {
background: rgb(255, 155, 155);
border: 2px solid rgb(255, 155, 155);
}
#menuToggler input:checked~#menu {
display: block;
width: 180px;
transform: translate(0%, 0);
}
#menuToggler input:checked~#menu a {
display: flex;
flex-flow: row;
font-size: 18px;
}
<div id="menuFix">
<div id="menuContainer">
<div id="menuToggler">
<input type="checkbox" id="menuTogglerCheckbox" />
<div class="menuBarCircle">
<span></span>
<span></span>
<span></span>
</div>
<ul id="menu">
<a href="#">
<li>Home</li>
</a>
<a href="#">
<li>Settings</li>
</a>
<a href="#">
<li>About Us</li>
</a>
<a href="#">
<li>Help</li>
</a>
</ul>
</div>
</div>
</div>
<div>Hello World I am with you this is the grace of God to be with you</div>
As a reply to your comment, here is a snippet where the menu will close if the user clicks inside the menu.
And some additional comments.
let menuToggleCheck = document.getElementById("menuTogglerCheckbox");
let menuFixBg = document.getElementById("menuFix");
let menu = document.getElementById("menuToggler");
menuToggleCheck.addEventListener('click', menuTogglerBackground)
function menuTogglerBackground() {
if (menuToggleCheck.checked) {
menuFixBg.style.backgroundColor = "rgba(126, 125, 125, 0.5)";
menuFixBg.style.width = "100vw";
menuFixBg.style.height = "100vh";
} else {
menuFixBg.style.backgroundColor = "transparent";
menuFixBg.style.width = "0vw"
menuFixBg.style.height = "0vh"
}
}
let menuContain = document.getElementById("menuContainer");
menuFixBg.addEventListener('click', function(e) {
if ( e.target.id === "menuTogglerCheckbox" ) {
// The User clicked on the Menu Toggle Box, which will have opened or closed the menu already, so do nothing
return true;
}
// Check to see if the Click Target is inside the Menu Container
let currentTarget = menuContain.contains(e.target);
if ( currentTarget ) {
// The user clicked inside the Menu Container
document.body.style.color = "red";
// Close the menu
menuToggleCheck.checked = false;
menuTogglerBackground();
} else {
// The user clicked outside the Menu Container
document.body.style.color = "blue";
// Maybe also close the menu?
//menuToggleCheck.checked = false;
//menuTogglerBackground();
}
});
* {
box-sizing: border-box;
}
body {
margin: 0px;
}
#menuFix {
position: fixed;
top: 0px;
}
#menuContainer {
width: 100px;
height: 100vh;
}
#menuToggler {
position: relative;
display: flex;
width: 90px;
height: 80px;
/* left: -100px; */
user-select: none;
}
#menuToggler input {
cursor: pointer;
position: absolute;
width: 40px;
height: 40px;
top: 7px;
left: 21px;
opacity: 0;
z-index: 2;
}
.menuBarCircle {
position: relative;
width: 40px;
height: 40px;
margin-top: 10px;
margin-left: auto;
margin-right: auto;
border: 1px solid black;
border-radius: 20px;
}
#menuToggler span {
position: relative;
display: block;
width: 26px;
height: 3px;
top: 10px;
left: 6px;
margin-bottom: 5px;
border-radius: 5px;
background: black;
transform-origin: 0px 0px;
transition: 0.2s;
z-index: 1;
}
#menuToggler span:nth-child(1) {
background: brown;
transform-origin: 0 0;
}
#menuToggler span:nth-child(3) {
background: brown;
transform-origin: 0 100%;
}
#menuToggler input:checked~.menuBarCircle span {
margin-left: 4px;
}
#menuToggler input:checked~.menuBarCircle span:nth-child(1) {
transform: rotate(45deg) translate(0px, -1px);
}
#menuToggler input:checked~.menuBarCircle span:nth-child(3) {
transform: rotate(-45deg) translate(0, 1px);
}
#menuToggler input:checked~.menuBarCircle span:nth-child(2) {
opacity: 0;
}
#menu {
position: absolute;
list-style-type: none;
width: 90px;
height: 100vh;
margin-top: auto;
padding: 50px 0;
background: white;
border-right: 1px solid black;
/* z-index: -1; */
transform: translate(-100%, 0);
transition: 0.5s width;
}
#menu a {
display: flex;
flex-flow: column;
text-decoration: none;
font-size: 14px;
width: 100%;
padding: 5px 10px;
margin: 5px 0;
color: black;
border: 2px solid white;
border-radius: 20px 0 0 20px;
}
#menu a li {
display: flex;
justify-content: center;
align-items: center;
}
#menu a:hover {
background: rgb(255, 155, 155);
border: 2px solid rgb(255, 155, 155);
}
#menuToggler input:checked~#menu {
display: block;
width: 180px;
transform: translate(0%, 0);
}
#menuToggler input:checked~#menu a {
display: flex;
flex-flow: row;
font-size: 18px;
}
<div id="menuFix">
<div id="menuContainer">
<div id="menuToggler">
<input type="checkbox" id="menuTogglerCheckbox" />
<div class="menuBarCircle">
<span></span>
<span></span>
<span></span>
</div>
<ul id="menu">
<a href="#">
<li>Home</li>
</a>
<a href="#">
<li>Settings</li>
</a>
<a href="#">
<li>About Us</li>
</a>
<a href="#">
<li>Help</li>
</a>
</ul>
</div>
</div>
</div>
<div>Hello World I am with you this is the grace of God to be with you</div>
im in the process of taking two projects that i found on instagram. i am making a random color generator and on the side of the text it shows a clipboard button so i can or who ever can randomly generate a color and copy the hex code. i have went over the code and both projects and i am getting a "Uncaught TypeError: Cannot read property 'select' of null " in the console.
the project can be found at the following link https://codepen.io/nhmalbone0311/pen/KKmYQbQ.
let letters = "0123456789ABCDEF";
const body = document.querySelector("body");
const colorElement = document.querySelector("#color");
function getColor() {
let color = "#";
for (let i = 0; i < 6; i++) {
color += letters[Math.floor(Math.random() * letters.length)];
}
body.style.backgroundColor = color;
colorElement.innerHTML = color;
}
function copyText() {
var copyText = document.getElementById("#color");
copyText.select();
document.execCommand("copy");
document.getElementById("notification").style.opacity = "1";
setTimeout(() => {
document.getElementById("notification").style.opacity = "0";
}, 1000);
}
console.log(copyText);
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Inconsolata', monospace;
height: 100vh;
display: flex;
align-items: center;
justify-content: center;
background: #494e6b;
transition: 0.1s;
}
/* p field */
.colors {
float: left;
margin-bottom: 20px;
font-size: 26px;
padding: 10px 57px;
text-align: center;
color: #fff;
background: #000;
}
/* btns */
.btn {
cursor: pointer;
width: 50px;
height: 47px;
border: none;
margin: 0 5px 0;
font-size: 25px;
}
.g-color {
padding: 5px 13px;
border: 3px solid #111;
letter-spacing: 1px;
outline: none;
font-size: 25px;
transition: 100ms ease-in-out;
cursor: pointer;
}
.g-color:hover {
outline: none;
color: red;
}
.tooltip {
position: relative;
display: flex;
align-item: center;
justify-content: center;
width: 180px;
height: 50px;
font-size: 20px;
padding: 10px;
border-radius: 10px;
bottom: 7rem;
left: 14rem;
color: #fff;
background: #98878f;
opacity: 0;
transition: .5s;
}
.tooltip:after {
position: absolute;
content: "";
width: 25px;
height: 25px;
top: -8rem;
right: 50px;
background: #985e6d;
transform: rotate(45deg);
}
<div class="container">
<p id="color" class="colors">#</p>
<button onclick="copyText()" class="btn"><i class="far fa-copy"></i></button>
<div class="generate-color">
<button onclick="getColor()" class="g-color">Generate Color</button>
</div>
<!-- notification -->
<div class="tooltip" id="notifaction">
<p>Text Copied!</p>
</div>
</div>
im using code pen as i do this as a hobby for now in its just easier for me to show my work off and have people me if i need it.
im just now working on getting out of tutorial hell and founding projects on the web in intergrading them into my own style and changing things up.
remove the # from the "#color" in var copyText = document.getElementById("#color");
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
}
};
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>