I'm trying to build a library where the user can write the info and the book and add it to the library. I created a modal form where the user can write the info and submit it.
This is the modal html
<form class="modal__container">
<div class="modal">
<div class="modal__content">
<label for="">Title:</label>
<input type="text" id="title">
</div>
<div class="modal__content">
<label for="">Author:</label>
<input type="text" id="author">
</div>
<div class="modal__content">
<label for="">Pages:</label>
<input type="number" id="pages">
</div>
<label for="">Have you read it?</label>
<div>
<label for="yes">Yes</label>
<input type="radio" name ="read" value="yes">
<label for="no">No</label>
<input type="radio" name ="read" value="no">
</div>
<button class="add__book">Add</button>
<button class="cancel">Cancel</button>
</div>
</form>
This is the function that closes the modal when clicking on the cancel button
function toggle() {
addBtn.addEventListener("click", () => {
modal.style.display = "block";
const cancel = document.querySelector(".cancel");
cancel.addEventListener("click", () => {
modal.style.display = "none";
})
})
}
toggle();
Here I have the constructor and the array to store the books
let myLibrary = [];
function Book(title, author, pages) {
this.title = title,
this.author = author,
this.pages = pages
}
Now I want to create a function that submits the new book
submitBook.addEventListener("click", addBookToLibrary);
function addBookToLibrary() {
let bookTitle = modalTitle.value;
let bookAuthor = modalAuthor.value;
let bookPages = modalPages.value;
let book = new Book(bookTitle, bookAuthor, bookPages);
myLibrary.push(book);
console.log(bookTitle)
console.log(bookAuthor)
console.log(bookPages)
toggle();
}
I see the info for half a second and then it disappears. I know I should use prevent default somewhere. I tried this
function addBookToLibrary(e) {
e.preventDefault();
let bookTitle = modalTitle.value;
let bookAuthor = modalAuthor.value;
let bookPages = modalPages.value;
let book = new Book(bookTitle, bookAuthor, bookPages);
myLibrary.push(book);
console.log(bookTitle)
console.log(bookAuthor)
console.log(bookPages)
toggle();
}
It displays the info correctly but it doesn't close the modal. How can I fix it?
You currently have an anonymous function that does what you want: close the modal. It's inside another anonymous function which opens the modal:
addBtn.addEventListener("click", () => {
modal.style.display = "block";
const cancel = document.querySelector(".cancel");
cancel.addEventListener("click", () => {
modal.style.display = "none";
});
});
You can "refactor" out two named functions from that code, like so:
const hideModal = () => {
modal.style.display = "none";
};
const showModal = () => {
modal.style.display = "block";
const cancel = document.querySelector(".cancel");
cancel.addEventListener("click", hideModal);
};
addBtn.addEventListener("click", showModal);
Then, inside your other event handlers, you can call either function:
function addBookToLibrary() {
// ...
hideModal();
}
Related
I'm trying to figure out how to make my form submit when enter is pressed inside the div that is acting as input. Any help?
Here is my code.
const socket = new WebSocket("ws://localhost:5000");
const Chat = () => {
let divText = "";
const SendMessage = (event) => {
event.preventDefault();
console.log(divText);
divText = "";
}
const HandleChange = (event) => {
divText = event.target.textContent;
}
return (
<div className='chat-div'>
<div className='chat-box'>
<span className='razmak'></span>
</div>
<form className='input-form' onSubmit={SendMessage} spellCheck='false'>
<div className='chat-input' contentEditable='true' onInput={HandleChange}></div>
<button className='send-button' type='submit'><AiOutlineSend/></button>
</form>
</div>
)
}
export default Chat;
What I'd do is update your div to use an onKeyDown like this:
const socket = new WebSocket("ws://localhost:5000");
const Chat = () => {
let divText = "";
const sendMessage = (event) => {
alert("submit");
event.preventDefault();
console.log(divText);
divText = "";
};
const handleChange = (e) => {
divText = e.target.textContent;
if (e.key === "Enter") {
sendMessage(e);
}
};
return (
<div className="chat-div">
<div className="chat-box">
<span className="razmak"></span>
</div>
<form className="input-form" onSubmit={sendMessage} spellCheck="false">
<div
className="chat-input"
contentEditable="true"
onKeyDown={(e) => handleChange(e)}
></div>
<button className="send-button" type="submit">
jhgj
</button>
</form>
</div>
);
};
export default Chat;
There's a couple of other things, some which I've not included above:
Lowercase the method names if they don't return JSX
The divText should ideally use the useState React hook
Consider using a standard input rather than a div, as this is semantically more correct, and accessible for people using screen readers.
I have a to do list that is creating two delete buttons per task for the second task item, three delete buttons for the third task etc. Here is my code.
//Submits the form
function submitForm() {
form.addEventListener('submit', function (e) {
e.preventDefault();
taskData = document.getElementById('activity').value;
addingTask(taskData);
form.reset(taskData);
return taskData;
});
}
//Adds a task element
function addingTask(taskData) {
taskElement = document.createElement('h3');
deleteButton = document.createElement('Button');
taskElement.innerHTML = taskData;
taskElement.id = 'taskElement';
deleteButton.innerHTML = 'Delete';
//deleteButton.id = taskData;
deleteButton.addEventListener('click', deletingTask);
document.body.appendChild(taskElement);
document.body.appendChild(deleteButton);
}
//Removes a task element
function deletingTask() {
taskElement.remove();
deleteButton.remove();
}
<body>
<form id="form"> <label for="activity">Activity</label><br> <input type="text" id="activity"
name="activity"><br><br> <input type="submit" value="Submit" onclick="submitForm()"> </form>
<!-- your content here... -->
<script src="script.js"></script>
</body>
You shouldn't create new event listeners each time you submit the form. Add the event listener only once:
//Submits the form
form.addEventListener('submit', function (e) {
e.preventDefault();
taskData = document.getElementById('activity').value;
addingTask(taskData);
form.reset(taskData);
return taskData;
});
//Adds a task element
function addingTask(taskData) {
taskElement = document.createElement('h3');
deleteButton = document.createElement('Button');
taskElement.innerHTML = taskData;
taskElement.id = 'taskElement';
deleteButton.innerHTML = 'Delete';
//deleteButton.id = taskData;
deleteButton.addEventListener('click', deletingTask);
document.body.appendChild(taskElement);
document.body.appendChild(deleteButton);
}
//Removes a task element
function deletingTask() {
taskElement.remove();
deleteButton.remove();
}
<form id="form">
<label for="activity">Activity</label><br> <input type="text" id="activity" name="activity">
<br><br>
<input type="submit" value="Submit">
</form>
The issue is you do this each time you submit
form.addEventListener('submit', function (e) {
Also form.reset does not take a parameter.
Lastly ne need to return the data in the submit event
You should delegate and have a div per task
const container = document.getElementById("container");
//Submits the form
form.addEventListener('submit', function(e) {
e.preventDefault();
taskData = document.getElementById('activity').value;
addingTask(taskData);
this.reset();
});
container.addEventListener("click", function(e) {
const tgt = e.target;
if (tgt.classList.contains("delete")) {
//Removes a task element
tgt.closest("div").remove();
}
})
//Adds a task element
function addingTask(taskData) {
const taskElement = document.createElement('div');
const header = document.createElement('h3');
deleteButton = document.createElement('Button');
header.innerHTML = taskData;
deleteButton.innerHTML = 'Delete';
deleteButton.classList.add("delete");
taskElement.appendChild(header);
taskElement.appendChild(deleteButton);
container.append(taskElement);
}
<form id="form">
<label for="activity">Activity</label>
<input type="text" id="activity" name="activity">
<input type="submit" value="Submit">
<div id="container"></div>
</form>
const toDoForm = document.querySelector(".todo__form"),
toDoInput = document.querySelector(".todo__input");
toDoList = document.querySelector("li");
let toDoArray = [];
function addToDoList() {
toDoForm.addEventListener('submit', event => {
toDoArray.push(toDoInput.value);
toDoList.innerHTML += `<ul>${toDoArray[toDoArray.length-1]}</ul>`;
event.preventDefault();
toDoInput.value = "";
});
}
function clearList() {
const toDoUl = document.querySelector("ul");
toDoForm.addEventListener('click', event => {
toDoArray = [];
toDoUl.parentNode.removeChild(toDoUl);
});
}
function init() {
addToDoList();
clearList();
}
init();
<h1>To-Do List</h1>
<div class="todo">
<form class="todo__form">
<input class="todo__input" type="text">
<input class="todo__submit" type="submit" value="Submit">
<input class="todo__clear" type="button" value="Clear">
</form>
</div>
<div class="todo-list">
<li></li>
</div>
I'm making a to-do list with javascript and i tried to use removeChild method to clear to-do list but when i run the code, it keeps getting an error like this -> Uncaught TypeError: Cannot read property 'parentNode' of null at HTMLFormElement. How can i solve it?
The query document.querySelector("ul"); is returning undefined because there is no ul element in the HTML. Try changing the div to ul tag
<ul class="todo-list">
<li></li>
</ul>
First, I thought you want remove one item at a time, then I made some changes which may be useful but you if you don't need it, you could remove delete function.
For adding an item, you enter a job name, for example 'Job1' an then press "Submit" button.
For deleting an item, you enter a job name, for example 'Job1' an then press "Delete" button.
Press 'Clear' to clear all items.
JavaScript:
<script>
let toDoArray = [];
let toDoForm;
window.onload = () => {
toDoForm = document.querySelector(".todo__form"),
toDoInput = document.querySelector(".todo__input");
toDoList = document.querySelector("ul");
clearButton = document.querySelector(".todo__clear");
deleteButton = document.querySelector(".todo__delete");
init();
};
function addToDoList() {
toDoForm.addEventListener('submit', event => {
toDoList.innerHTML += `<li>${toDoInput.value}</li>`;
event.preventDefault();
toDoInput.value = "";
});
}
function deleteItem() {
deleteButton.addEventListener('click', event => {
const toDoUl = document.querySelector("ul");
let allLi = document.querySelectorAll('li');
allLi.forEach(li => {
if (li.innerHTML === toDoInput.value)
toDoUl.removeChild(li);
});
toDoInput.value = "";
});
}
function clearList() {
clearButton.addEventListener('click', event => {
const toDoUl = document.querySelector("ul");
toDoUl.innerHTML = '';
});
}
function init() {
addToDoList();
deleteItem();
clearList();
}
</script>
HTML:
<body>
<h1>To-Do List</h1>
<div class="todo">
<form class="todo__form">
<input class="todo__input" type="text">
<input class="todo__submit" type="submit" value="Submit">
<input class="todo__delete" type="button" value="Delete">
<input class="todo__clear" type="button" value="Clear">
</form>
</div>
<div class="todo-list">
<ul></ul>
</div>
<script src="todo.js"></script>
</body>
First, you need to change <li></li> to <ul></ul>. You can get help from w3school link.
There is a StackOverflow answer about this issue Stackoverflow. You can check that.
I am trying to make a login system with a set password but it only sees the first password that I set with javascript.
<p id="loginuser" style="display: block">Username:
<input type="text" name="text1">
</p>
<p id="loginpass" style="display: block">Password:
<input type="password" name="dasnk2">`
</p>
<input id="login" style="display: block" type="button" value="Log In" name="Submit" onclick="javascript:validate(document.getElementsByName("text1")[0].value,"Harrison",document.getElementsByName("dasnk2")[0].value,"88888888a"); validate(document.getElementsByName("text1")[0].value,"Isaac",document.getElementsByName("dasnk2")[0].value,"Tewst"); validate(document.getElementsByName("text1")[0].value,"Adam",document.getElementsByName("dasnk2")[0].value,"faa222014"); validate(document.getElementsByName("text1")[0].value,"Kelvin",document.getElementsByName("dasnk2")[0].value,"six921six921"); validate(document.getElementsByName("text1")[0].value,"Alap",document.getElementsByName("dasnk2")[0].value,"99999999nine")" >
this is my function for validating to be a bit more clear. (editied)
function validate(text1,dasnk2,text3,text4) {
if (text1 === dasnk2 && text3 === text4) {
var redirect = document.getElementById('redirect');
var embed = document.getElementById("embed");
redirect.style.display = "block";
embed.style.display = "none";
setTimeout(function() {
embed.style.display = "block";
redirect.style.display = "none";
loginuser.style.display = "none";
loginpass.style.display = "none";
login.style.display = "none";
header.style.display = "none";
}, 5000);
} else {
var incorrect = document.getElementById('incorrect');
incorrect.style.display = "block";
setTimeout(function() {
incorrect.style.display = "none";
}, 2000);
}
}
You have multiple onlick events. Each one overwrites the previous one. So in the end the only onclick event that will be called is the last one. If you want to call multiple things inside an inline event handler you need to use semicolons.
onclick="function1(); function2(); function3();"
In your case validate is probably trying to cancel the submission event. You are not cancelling it since there is no return. So it would have to be
onclick="return function1() && function2() && function3();"
Ideally you would not be using inline event handlers, but you would bind the event with addEventListener.
document.getElementById("myForm").addEventListener("submit", function () {
var valid1 = validate(...)
var valid2 = validate(...)
var valid3 = validate(...)
return valid1 && valid2 && valid3;
});
I have a function which enables the button 2(id keuze1) and button 3 ( id keuze 3) If i press button 1 (id = naam).
function init() {
let startKnop = document.getElementsByTagName("button")[0].addEventListener("click", startClicked, false);
}
function startClicked(event) {
let knop2 = document.getElementById("keuze1");
knop2.removeAttribute("disabled");
let knop3 = document.getElementById("keuze2");
knop3.removeAttribute("disabled");
toonVraag();
}
function toonVraag(event) {
let i = vraagTeller.value;
let vraag = document.getElementById('vraag');
vraag.innerHTML = "Hello World";
}
<label for="naam">Code: </label><input type="text" id="naam" />
</div>
<button disabled>Start</button>
<div>
<p id="vraag">Een vraag</p>
<button id="keuze1" disabled>Keuze1</button>
<button id="keuze2" disabled>Keuze2</button>
</div>
So it successfully runs the function startClicked(), but stops immediately.
If I add the code event.preventDefault() it doesn't go through to changing the text from my element(id = vraag).
Seems to work just fine, as exemplified in this JSFiddle
I did some clean-up though:
Removed the disabled attribute from the first button
Removed the </div> from the 2nd line
Added call to the init() function
As such:
function init() {
let startKnop = document.getElementsByTagName("button")[0].addEventListener("click", startClicked, false);
}
init();
function startClicked(event) {
let knop2 = document.getElementById("keuze1");
knop2.removeAttribute("disabled");
let knop3 = document.getElementById("keuze2");
knop3.removeAttribute("disabled");
toonVraag();
}
function toonVraag(event) {
let vraag = document.getElementById('vraag');
vraag.innerHTML = "Hello World";
}
<label for="naam">Code: </label><input type="text" id="naam" />
<button>Start</button>
<div>
<p id="vraag">Een vraag</p>
<button id="keuze1" disabled>Keuze1</button>
<button id="keuze2" disabled>Keuze2</button>
</div>