Dynamically setting background image on Grid cell with JS - javascript

The program I am creating is a meme generator. I have a div container set up with display:grid with a few tags inside of that which act as the top and bottom text for the meme. I'm trying to dynamically set the background image for the grid cell using plain vanilla JS. When I attach the link inside the CSS file it works perfectly, but using JS the background-image is never set when i check inside the browser. I put a big arrow so you can see where I am attempting to set the image
const imageLink = document.querySelector('#imageLink');
const topText = document.querySelector('#topText');
const bottomText = document.querySelector('#bottomText');
const memeDiv = document.querySelector('#meme');
//listener for submit
document.addEventListener("submit", function(e) {
e.preventDefault();
//if the user doesn't enter an image, or if they don't enter any text, don't generate the meme when they submit.
if (imageLink.value === "") {
return;
} else if (topText === "" && bottomText === "") {
return;
}
console.log(imageLink.value);
//create elements
var div = document.createElement("div");
//set attribute for div containing our memes
div.setAttribute("id", "meme");
//When the page loads apply the users photo to the background of the grid
window.addEventListener('DOMContentLoaded', function() {
memeDiv.style.backgroundImage = `url(${imageLink.value})`; // < -- -- -
});
//create text and remove button for the memes
const top = document.createElement("p"); //for top text
const bottom = document.createElement("p"); //for bottom text
const removeBtn = document.createElement("input");
//remove button attributes
removeBtn.setAttribute("id", "remove");
removeBtn.setAttribute("type", "image");
removeBtn.setAttribute("height", "200px");
removeBtn.setAttribute("width", "200px");
removeBtn.setAttribute(
"src",
"https://www.freeiconspng.com/uploads/x-png-33.png"
);
//set attributes for text
top.setAttribute("id", "top");
top.innerText = topText.value;
bottom.setAttribute("id", "bottom");
bottom.innerText = bottomText.value;
//put the top and bottom text with the remove button together with the same div
div.appendChild(top);
div.appendChild(bottom);
div.appendChild(removeBtn);
//append to the div
document.querySelector("#memeContainer").appendChild(div);
//reset
imageLink.value = "";
topText.value = "";
bottomText.value = "";
})
document.addEventListener("click", function(e) {
if (e.target.id === "remove") {
e.target.parentElement.remove();
} else {
return;
}
})
* {
margin: 0px;
}
#formContainer {
background-color: blue;
margin-bottom: 5px;
text-align: center;
}
h1 {
text-align: center;
background-color: blue;
margin: 0px;
}
#memeContainer {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: repeat(3, 300px);
grid-gap: 5px;
}
#top,
#bottom,
#remove {
position: relative;
display: inline;
}
#top {
left: 225px;
z-index: 1;
font-family: Impact;
font-size: 40px;
/* color:white; */
}
#bottom {
top: 300px;
left: 225px;
z-index: 2;
font-family: Impact;
font-size: 40px;
/* color:white; */
}
#remove {
top: -150px;
left: 180px;
z-index: 3;
/* filter: opacity(1%); */
}
#remove:hover {
z-index: 3;
filter: opacity(25%);
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Meme Generator</title>
<link rel="stylesheet" href="app.css">
</head>
<body>
<h1>MEME GENERATOR</h1>
<div id="formContainer">
<form>
<input id="imageLink" type="text" placeholder="please link to an image">
<input id="topText" type="text" placeholder="TOP TEXT">
<input id="bottomText" type="text" placeholder="BOTTOM TEXT">
<button type="submit">submit</button>
</form>
</div>
<div id="memeContainer"></div>
<script src="app.js"></script>
</body>
</html>

The DOMContentLoaded event is only called once whenever all HTML have been loaded. So you are only adding an event listener which never fires and thus nothing happens.
window.addEventListener('DOMContentLoaded', function() {
memeDiv.style.backgroundImage = `url(${imageLink.value})`;
});
Remove the event listener and correct the memeDiv variable name to div and your code will run.
div.style.backgroundImage = `url(${imageLink.value})`;
const imageLink = document.querySelector('#imageLink');
const topText = document.querySelector('#topText');
const bottomText = document.querySelector('#bottomText');
const memeDiv = document.querySelector('#meme');
//listener for submit
document.addEventListener("submit", function(e) {
e.preventDefault();
//if the user doesn't enter an image, or if they don't enter any text, don't generate the meme when they submit.
if (imageLink.value === "") {
return;
} else if (topText.value === "" && bottomText.value === "") {
return;
}
console.log(imageLink.value);
//create elements
var div = document.createElement("div");
//set attribute for div containing our memes
div.setAttribute("id", "meme");
//When the page loads apply the users photo to the background of the grid
div.style.backgroundImage = `url(${imageLink.value})`; // < -- -- -
//create text and remove button for the memes
const top = document.createElement("p"); //for top text
const bottom = document.createElement("p"); //for bottom text
const removeBtn = document.createElement("input");
//remove button attributes
removeBtn.setAttribute("id", "remove");
removeBtn.setAttribute("type", "image");
removeBtn.setAttribute("height", "200px");
removeBtn.setAttribute("width", "200px");
removeBtn.setAttribute(
"src",
"https://www.freeiconspng.com/uploads/x-png-33.png"
);
//set attributes for text
top.setAttribute("id", "top");
top.innerText = topText.value;
bottom.setAttribute("id", "bottom");
bottom.innerText = bottomText.value;
//put the top and bottom text with the remove button together with the same div
div.appendChild(top);
div.appendChild(bottom);
div.appendChild(removeBtn);
//append to the div
document.querySelector("#memeContainer").appendChild(div);
//reset
imageLink.value = "";
topText.value = "";
bottomText.value = "";
})
document.addEventListener("click", function(e) {
if (e.target.id === "remove") {
e.target.parentElement.remove();
} else {
return;
}
})
* {
margin: 0px;
}
#formContainer {
background-color: blue;
margin-bottom: 5px;
text-align: center;
}
h1 {
text-align: center;
background-color: blue;
margin: 0px;
}
#memeContainer {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: repeat(3, 300px);
grid-gap: 5px;
}
#top,
#bottom,
#remove {
position: relative;
display: inline;
}
#top {
left: 225px;
z-index: 1;
font-family: Impact;
font-size: 40px;
/* color:white; */
}
#bottom {
top: 300px;
left: 225px;
z-index: 2;
font-family: Impact;
font-size: 40px;
/* color:white; */
}
#remove {
top: -150px;
left: 180px;
z-index: 3;
/* filter: opacity(1%); */
}
#remove:hover {
z-index: 3;
filter: opacity(25%);
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Meme Generator</title>
<link rel="stylesheet" href="app.css">
</head>
<body>
<h1>MEME GENERATOR</h1>
<div id="formContainer">
<form>
<input id="imageLink" type="text" placeholder="please link to an image">
<input id="topText" type="text" placeholder="TOP TEXT">
<input id="bottomText" type="text" placeholder="BOTTOM TEXT">
<button type="submit">submit</button>
</form>
</div>
<div id="memeContainer"></div>
<script src="app.js"></script>
</body>
</html>

Related

why grid cells wont go below 32px width and height?

im trying to make static grid with a button that can change number of boxes in it (from 16x16 to 64x64 and anything between). Grid is 40rem x 40rem, when i try to change manually number of boxes in makeGrid() function it works fine up to 20 (boxes change size accordingly), but anything above 20 stays the same size and gets cutoff from my grid. If there is no grid css overflow property stated, grid width change depending on number of boxes but boxes themself won't shrink
my code:
size button is not working yet, grid size need to be changed mannualy in makeGrid function
const grid = document.getElementById('grid');
const size = document.getElementById('size');
const eraser = document.getElementById('eraser');
const color = document.getElementById('color');
const gridBorder = document.getElementById('grid-borders');
const clear = document.getElementById('clear');
// grid
function makeGrid(number) {
number = number || 16;
let cellWidth = 40 / number + 'rem';
let cellHeight = 40 / number + 'rem';
grid.style.gridTemplateColumns = `repeat( ${number}, 1fr)`;
grid.style.gridTemplateRows = `repeat(${number}, 1fr)`;
for (let i = 0; i < number * number; i++) {
let cell = document.createElement('div');
grid.appendChild(cell).id = 'box';
cell.classList.add('border');
cell.classList.add('box');
cell.style.backgroundColor = 'white';
cell.style.width = cellWidth;
cell.style.height = cellHeight;
}
size.textContent = `${number} x ${number}`;
}
makeGrid();
// drawing on hover
color.addEventListener('click', function () {
grid.addEventListener('mouseover', function (e) {
e.target !== grid ? (e.target.style.backgroundColor = 'black') : null;
});
});
function changeColor(event) {
event.target.style.backgroundColor = 'black';
}
// erase functionality
eraser.addEventListener('click', function () {
grid.addEventListener('mouseover', function (e) {
e.target !== grid ? (e.target.style.backgroundColor = 'white') : null;
});
});
// grid borders
const allBoxes = document.querySelectorAll('.box');
gridBorder.addEventListener('click', function () {
allBoxes.forEach((box) => {
box.classList.toggle('no-border');
box.classList.toggle('border');
});
});
// clear button
clear.addEventListener('click', function () {
allBoxes.forEach((box) => {
box.style.backgroundColor = 'white';
});
});
// size button
// size.addEventListener('click', function () {
// let number = prompt(`Enter grid size less or equal to 100`);
// if (number !== Number.isInteger()) {
// return;
// } else if (number > 100) {
// number = prompt(`Enter grid size greater or equal to 100`);
// }
// });
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
height: 100vh;
background-color: aquamarine;
}
#grid {
display: grid;
justify-content: center;
border: 1px solid #ccc;
width: 40rem;
height: 40rem;
min-width: 0;
min-height: 0;
overflow: hidden;
}
.box {
padding: 1em;
}
#title {
display: flex;
align-items: flex-end;
justify-content: center;
height: 180px;
}
#container {
display: flex;
height: 60%;
width: 1259px;
align-items: flex-start;
justify-content: flex-end;
gap: 20px;
padding-top: 20px;
}
#menu {
display: flex;
flex-direction: column;
gap: 10px;
}
.border {
outline: 1px solid black;
}
.no-border {
outline: none;
}
.black-bg {
background: black;
}
.white-bg {
background: white;
}
<!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" />
<title>Etch-a-Sketch</title>
<link rel="stylesheet" href="style.css" />
<script src="script.js" defer></script>
</head>
<body>
<div id="title">
<h1>Etch-a-Sketch</h1>
</div>
<main id="container">
<div id="menu">
<button id="size"></button>
<button id="color">Color</button>
<button id="eraser">Eraser</button>
<button id="clear">Clear</button>
<button id="grid-borders">Grid Borders</button>
</div>
<div id="grid"></div>
</main>
</body>
</html>
"Why won't my grid cells go below 32px?" - have you checked your padding (hint: 32px is exactly equal to 2 * 16px which in turn is exactly equal to your padding of 1em with most browsers implementing a default font-size of 16px). –
David Thomas
box padding was set to 1em which caused my problem, after deleting it my grid worked as intended

looking for why list does not display when adding task to the to do

Good day folks,
I am creating a to-do app, and so far when I enter the task in via the input the console shows my object firing but does not display it on the screen. Please look at my code and help me point out the issue, I have been debugging this for some time today.
HTML:
<!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="css/to-doStylesheet.css">
<title>To-Do App</title>
</head>
<body>
<div class=container>
<div class= base>
<div class = screen>
<img src="images/WarGreymon_Render.png" alt="Wargreymon">
<div id ="speach-bubble"> What is on your
agenda for today?
</div>
<div class = "dateTime">
</div>
</div>
<div class = "nameInput" id = "inputContainer">
<form class ="form">
<input type="text" class ="userInput" placeholder="Add Agenda and press enter">
<input type="submit" value ="Add">
</form>
</div>
</div>
<ul class="list"></ul>
<script src="js/add-task.js"></script>
</body>
</html>
CSS
.form
{
margin-left: 400px;
}
.userInput
{
width: 394px;
height: 30px;
background-color: #B62626;
font-family: Digimon Basic;
color: #33D61A;
margin-left: -359px;
}
.userInput ::placeholder
{
color: #33D61A;
font-family: Digimon Basic;
}
.list:empty
{
display: none;
}
.list
{
list-style: none;
margin-bottom: 20px;
}
.input[type="checkbox"] {
display: none;
}
.tick {
width: 30px;
height: 30px;
border: 3px solid #333;
border-radius: 50%;
display: inline-flex;
justify-content: center;
align-items: center;
cursor: pointer;
}
.todo-item {
margin-bottom: 10px;
width: 100%;
display: flex;
align-items: center;
justify-content: space-between;
}
.todo-item span {
flex-grow: 1;
margin-left: 10px;
margin-right: 10px;
font-size: 22px;
}
JS
let tasks = [];
const currentdt = new Date()
function todo(text) {
const todo = {
text,
checked: false,
id: Date.now(),
timestamp: currentdt
};
tasks.push(todo);
console.log(tasks);
}
// Select the form element
const form = document.querySelector('.form');
// Add a submit event listener
form.addEventListener('submit', event => {
// prevent page refresh on form submission
event.preventDefault();
// select the text input
const input = document.querySelector('.userInput');
// Get the value of the input and remove whitespace
const text = input.value.trim();
if (text !== '') {
todo(text);
input.value = '';
input.focus();
}
});
//This function is to display new to do on the screen
function displaytasks(todo)
{
const list = document.querySelector('list');
const isChecked = todo.checked ? 'done': '';
const addedList = document.createElement("li");
addedList.setAttribute('class', `todo-item ${isChecked}`);
addedList.setAttribute('data-key', todo.timestamp);
addedList.innerHTML = `<input id="${todo.timestamp}" type="checkbox"/>
<label for="${todo.timestamp}" class="tick js-tick"></label>
<span>${todo.text}</span>
<button class="delete-todo js-delete-todo">
<img class = "delete" src="images/delete.png" alt="delete icon">
</button>`;
list.append(addedList);
}
So I am busy with the js file at the moment, I think it has to do something with the innerHTML, but I am not sure what exactly is wrong there, because when I look in the console on the HTML side I do not see the <ul class="list"></ul> firing at all to bring the new HTML elements.
Your help will be much appreciated
It looks like the code to display the todos is not being called, so I would recommend you add in a function call after reading in a new todo.
...
const text = input.value.trim();
if (text !== '') {
todo(text);
input.value = '';
input.focus();
displaytasks(tasks); // Show tasks after submission
}
});
//This function is to display new to do on the screen
function displaytasks(todo)
{
const list = document.querySelector('.list');
...

Why is javascript not recognizing my input as a varaible?

I'm working on this piece of code, and, when you enter you name through the settings button, the code should save your name in the variable "inputname" so when you speak "hello" to the program, the program should output "Hello" + the name you entered, but for some reason it won't work. Why is that?
The code is attached below and the demo website is linked here: https://javascript-test-3.stcollier.repl.co/
function record() {
var recognition = new webkitSpeechRecognition();
recognition.lang = "en-GB";
recognition.start();
recognition.continuous = true;
recognition.onresult = function(event) {
let transcript = event.results[0][0].transcript;
var str = transcript;
let msg_hello = ['Hello ' + inputname, 'Hello!', 'Hey ' + inputname];
if (str.includes('hello')) {
document.getElementById("output").innerHTML = (msg_hello[Math.floor(Math.random() * msg_hello.length)]);
responsiveVoice.speak(msg_hello[Math.floor(Math.random() * msg_hello.length)]);
} else {
document.getElementById('output').innerHTML = "I don't know what you mean."
responsiveVoice.speak(msg_notunderstood[Math.floor(Math.random() * msg_notunderstood.length)]);
}
document.getElementById('speechToText').value = event.results[0][0].transcript;
}
}
//Mic Trigger Key
document.body.onkeyup = function(e) {
if (e.keyCode == 32) {
record()
}
}
//Modal
var modal = document.getElementById("myModal");
var btn = document.getElementById("myBtn");
var span = document.getElementsByClassName("close")[0];
btn.onclick = function() {
modal.style.display = "block";
}
span.onclick = function() {
modal.style.display = "none";
}
window.onclick = function(event) {
if (event.target == modal) {
modal.style.display = "none";
}
}
//Input
function saveName() {
var inputname = document.getElementById('savedName').value;
alert("You entered your name as " + inputname)
return false;
}
#output {
text-align: center;
font-family: 'Times New Roman', Times, serif;
font-size: 20px;
}
/* Modal Stuff */
/* The Modal (background) */
.modal {
display: none; /* Hidden by default */
position: fixed; /* Stay in place */
z-index: 1; /* Sit on top */
padding-top: 100px; /* Location of the box */
left: 0;
top: 0;
width: 100%; /* Full width */
height: 100%; /* Full height */
overflow: auto; /* Enable scroll if needed */
background-color: rgba(0,0,0,0.4); /* Black w/ opacity */
}
/* Modal Content */
.modal-content {
background-color: #fefefe;
margin: auto;
padding: 20px;
border: 1px solid #888;
width: 80%;
}
/* The Close Button */
.close {
color: #aaaaaa;
float: right;
font-size: 28px;
font-weight: bold;
}
.close:hover,
.close:focus {
color: #000;
text-decoration: none;
cursor: pointer;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="stylesheet" href="style.css">
<title>Document</title>
</head>
<body>
<label for="Speech Recognition">Speech Recognition</label>
<input type="text" name="" id="speechToText" placeholder="Speak Something" disabled="disabled">
<button onclick="record()">Record</button>
<p id="output"></p>
<button id="myBtn">Settings</button>
<div id="myModal" class="modal">
<div class="modal-content">
<span class="close">×</span>
<input placeholder="Enter your name" type="text" size="12" id="savedName" />
<button onclick="return saveName();">Save</button><span title="We use your name for making your experience with Argon more personal." style="cursor:help;"> ?</span>
<script src="https://code.responsivevoice.org/responsivevoice.js?key=x9uXdCB8"></script>
<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
<script src="script.js"></script>
</body>
</html>
Thanks for any help.
When you define a variable (using var) inside a function, that confines that variable to that function only. Define inputname outside of the functions so other functions have access to it
var inputname
function record() {
....
if (!inputname) inputname = 'You'; // default
let msg_hello = ['Hello ' + inputname, ....
....
}
function saveName() {
inputname = document.getElementById('savedName').value;
...

JavaScript modal is unable to open

I'm making a note taker app that gives you the option to view said note in a modal whenever the button is clicked. The HTML for the note and modal is dynamically generated by event listeners. There are two ways the close the modal, by clicking the "X" button or by clicking outside of the modal. The program has full functionality whenever only one note is generated, but once I generate a second note the code breaks down. Once this happens only I'm able to open the modal of the first note generated, but not close it. And the second one won't open whatsoever. How could I fix this issue?
class Input {
constructor(note) {
this.note = note;
}
}
class UI {
addNote(input) {
// Get table body below form
const content = document.querySelector(".content");
// Create tr element
const row = document.createElement("tr");
// Insert new HTML into div
row.innerHTML = `
<td>
${input.note}
<br><br>
<button class="modalBtn">View Note</button>
</td>
`;
content.appendChild(row);
// Event listener to make modal
document.querySelector(".modalBtn").addEventListener("click", function(e) {
// Get container div
const container = document.querySelector(".container");
// Create div
const div = document.createElement("div");
// Assign class to it
div.className = "modal";
// Insert HTML into div
div.innerHTML = `
<div class="modal-content">
<span class="closeBtn">×</span>
<div>
<p>${input.note}</p>
</div>
</div>
`;
// Append the new div to the container div
container.appendChild(div);
// Get modal
const modal = document.querySelector(".modal");
// Event listener to close modal when "x" is clicked
document.querySelector(".closeBtn").addEventListener("click", function() {
container.removeChild(modal);
});
// Event listener to close when the window outside the modal is clicked
window.addEventListener("click", function(e) {
if (e.target === modal) {
container.removeChild(modal);
}
});
});
}
// Clear input field
clearInput() {
note.value = "";
}
}
// Event listener for addNote
document.getElementById("note-form").addEventListener("submit", function(e) {
// Get form value
const note = document.getElementById("note").value;
// Instantiate note
const input = new Input(note);
// Instantiate UI
const ui = new UI();
// Validate form (make sure input is filled)
if (note === "") {
// Error alert
alert("Please fill in text field!");
}
else {
// Add note
ui.addNote(input);
// Clear input field
ui.clearInput();
}
e.preventDefault();
});
h5 {
color: green;
}
.modal {
position: fixed;
z-index: 1;
left: 0;
top: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
}
.modal-content {
background-color: #fff;
margin: 20% auto;
padding: 30px;
width: 70%;
box-shadow: 0 5px 8px 0 rgba(0, 0, 0, 0.2), 0 7px 20px 0 rgba(0, 0, 0, 0.17);
animation-name: modalopen;
animation-direction: 1s;
}
.closeBtn {
color: #aaa;
/* float: right; */
font-size: 30px;
margin-bottom: 1rem;
padding-bottom: 1rem;
}
.closeBtn:hover,
.closeBtnBtn:focus {
color: #000;
text-decoration: none;
cursor: pointer;
}
.closeBtn + div {
margin-top: 2rem;
}
#keyframes modalopen {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/skeleton/2.0.4/skeleton.css" integrity="sha512-5fsy+3xG8N/1PV5MIJz9ZsWpkltijBI48gBzQ/Z2eVATePGHOkMIn+xTDHIfTZFVb9GMpflF2wOWItqxAP2oLQ==" crossorigin="anonymous" />
<link rel="stylesheet" href="style.css">
<title>Note Taker</title>
</head>
<body>
<div class="container">
<h1>Note Taker</h1>
<h5>Add A New Note:</h5>
<form id="note-form">
<div>
<label>Note:</label>
<textarea name="Note" id="note" class="u-full-width"> </textarea>
</div>
<div>
<button type="submit" class="button-primary">Add Note</button>
</div>
</form>
<table>
<tbody class="content"></tbody>
</table>
</div>
<script src="app.js"></script>
</body>
</html>
Fist of all.. I love your syntaxt!! Best I've seen so far! second.. you do a general query Selector and don't handle them separately. Can that be an issue?
EDIT:
Because of reasons I'll reformulated my answer..
document.querySelector('class') returns an Html-Collection with DOM element references containing the specified html class and should be handled separately.

Enter the prototype of an Object.prototype.function(), where all the EventListeners are safed (Javascript)

I am working on an assignment, that constructs a small library. The project requires, that the user can input the title of a book, its author, number of pages and if the user has already read it. Then the content gets displayed on the page.
Here's the code (work in progress):
let myLibrary = [];
let submitBtn = document.querySelector("#submitBtn");
let textInput = document.querySelectorAll("input");
let addNew = document.getElementById("addNew");
let fieldSet = document.getElementById("fieldset");
let cancelBtn = document.querySelector("#cancelBtn");
let bookDisplay = document.getElementById("bookDisplay");
let flexItems = document.getElementsByClassName("flexItems");
// object Constructor for new books
class Book {
constructor(title, author, pages, read) {
this.title = title;
this.author = author;
this.pages = pages;
this.read = read;
}
}
Book.prototype.addToDisplay = function() {
let newDiv = document.createElement("div");
bookDisplay.appendChild(newDiv).className = "flexItems";
let newSpan = document.createElement("span");
flexItems[myLibrary.length-1].appendChild(newSpan).className = "spanItem";
newSpan.innerText = this.title;
this.read === true ? flexItems[myLibrary.length-1].style.backgroundColor = "green" :
flexItems[myLibrary.length-1].style.backgroundColor = "red";
newDiv.addEventListener("mouseenter", moreInfo => {
newSpan.childNodes[0].nodeValue = this.author + "\n" + this.title + "\n" + this.pages + " pages";
})
newDiv.addEventListener("mouseleave", defaultInfo => {
newSpan.childNodes[0].nodeValue = this.title;
})
}
// creates a new instance of Book and pushes the object into the array
let addToLibrary = function addToLibrary() {
newBook = new Book(textInput[0].value, textInput[1].value, textInput[2].value, textInput[3].checked)
myLibrary.push(newBook);
newBook.addToDisplay();
};
// eventlistener, to submit a new Book to the library
submitBtn.addEventListener("click", addToLibrary);
// sets the form's display from block to non-visible
let cancel = function cancel() {
fieldSet.style.display = "none";
}
// cancels the form and returns back
cancelBtn.addEventListener("click", cancel);
// sets the form's display from non-visible to visible
let openForm = function openForm() {
fieldSet.style.display = "block";
}
// opens form to add new book
addNew.addEventListener("click", openForm);
body {
margin-left: 20px;
}
h1 {
text-align: center;
}
#fieldset {
position: fixed;
z-index: 2;
border: none;
display: none;
background: #3CBC8D;
border-radius: 10px;
right: 1%;
top: 2%;
width: 400px;
height: auto;
overflow: auto;
}
button {
cursor: pointer;
}
.display {
display: flex;
flex-direction: row;
flex-wrap: wrap;
position: relative;
}
.flexItems {
position: relative;
display: flex;
margin: 5px;
color: black;
font: Georgia;
font-size: 20px;
height: 200px;
width: 200px;
align-items: center;
border: 2px solid gray;
transition: 500ms;
border-radius: 5px;
}
.spanItem {
width: 100%;
text-align: center;
white-space: wrap;
overflow: hidden;
text-overflow: ellipsis;
}
.display .flexItems:focus,
.display .flexItems:hover {
transform: scale(1.2);
z-index: 1;
}
#addNew {
position: fixed;
z-index: 2;
border: none;
background: #3CBC8D;
color: white;
border-radius: 10px;
right: 2%;
top: 2%;
width: 100px;
height: 50px;
overflow: auto;
cursor: pointer;
}
/*. Could be additionally used for the hover-effect, but doesnt look that nice for more than one row
flexItems:hover ~.flexItems {
transform: translateX(25%);
}
.display:focus-within .flexItems,
.display:hover .flexItems {
transform: translateX(-25%);
}
.flexItems:focus ~.flexItems,
.flexItems:hover ~.flexItems {
transform: translateX(25%);
} */
<!DOCTYPE html>
<head>
<meta charset="UTF-8">
<link href="style.css" rel="stylesheet" type="text/css" />
<script src="script.js" defer></script>
<title>Library</title>
</head>
<body>
<div><h1>My book library</h1></div>
<div id="bookDisplay" class="display">
</div>
<div>
<button id="addNew">Test</button>
</div>
<fieldset id="fieldset">
<form id="form">
<div>
<label for="title">Title: </label>
<input type="text" name="title" id="title" class="usrInput">
</div>
<div>
<label for="author">Author: </label>
<input type="text" name="author" id="author" class="usrInput">
</div>
<div>
<label for="number">Number of pages: </label>
<input type="number" name="number" id="number" class="usrInput">
</div>
<div>
<label for="read">Already read?: </label><br>
Y <input type="radio" name="read" id="read" value="Y" class="read">
N <input type="radio" name="read" id="read" value="N" class="read">
</div>
<button id="submitBtn" type="button">Submit</button>
<button id="cancelBtn" type="button">Cancel</button>
</fieldset>
</div>
</body>
</html>
**My question: ** The code is working until here. But I have my concerns with the mouseenter-Eventlistener. On mouseenter, I want to add a <button>, to edit the book's value. And maybe there is moreto be added in the future. That would mean the àddToDisplay() function eventually will get clunky. So I was wondering, if I could enter the Object.prototype of the addToDisplay() function and store all eventListeners in its prototype. Is this possible in Javascript?
The only way I could solve it right now is, to write an extra function for the eventlisteners. But it seems, that this way, I'm just going back to normal function expressions with dozens of values to pass by:
Book.prototype.addToDisplay = function() {
// (...)
mousehover(this, newDiv, newSpan)
}
let mousehover = function mousehover(test, newDiv, newSpan) {
newDiv.addEventListener("mouseenter", moreInfo => {
newSpan.childNodes[0].nodeValue = test.author + "\n" + test.title + "\n" + test.pages + " pages";
})
newDiv.addEventListener("mouseleave", defaultInfo => {
newSpan.childNodes[0].nodeValue = test.title;
})
}
Hope I got the problem across. It's the first assignment to Objects I'm working on.
Thanks for any answers and links to informative sources.

Categories

Resources