I want to add books to a library. After entering info to input and submitting the books array stay empty. I'll post pictures so you can understand better. Also sorry for messy code. I'll clean up after getting it to work.
console.log after adding a book
const books = [];
const submitBook = () => {
const bookName = document.querySelector('#title').value;
const bookAuthor = document.querySelector('#author').value;
const bookYear = document.querySelector('#year').value;
// let book = new Book(bookName.value, bookAuthor.value, bookYear.value);
books.push({
'name':bookName,
'author':bookAuthor,
'year':bookYear
});
alert("Book added.");
}
<label for="title">Title:</label><br>
<input type="text" id="title" name="title" required><br>
<label for="author">Author:</label><br>
<input type="text" id="author" name="author" required><br>
<label for="year">Year:</label><br>
<input type="number" id="year" name="year" required><br>
<button onclick="submitBook()">Add book</button>
Your code seems to work. I've taken the liberty to simplify you code somewhat. It is generally not a good idea to use inline event handling (onclick=... within html), so moved the handler to the code section. Also added a button to show added books.
let books = [];
let to = null;
const clearAfter = (delay = 2) => setTimeout(() => console.clear(), delay * 1000);
const format = obj => JSON.stringify(obj).split("},{").join("},\n{");
const submitBook = () => {
let book = {};
document.querySelectorAll("input")
.forEach(inp => book[inp.name] = inp.value);
books.push(book);
console.clear();
// console.log here to see the result immediately,
// otherwise there may not be any result yet
console.log(`Added:\n${format(book)}`);
}
document.addEventListener("click", evt => {
if (evt.target.id === "addbook") {
submitBook();
} else if (evt.target.id === "showbooks") {
console.clear();
console.log(`${books.length || "No"} added books\n${
books.length < 1 ? "-" : format(books)}`);
}
// remove the log (to make buttons visible again in the SO-run window)
clearTimeout(to);
to = clearAfter();
});
<label for="title">Title:</label><br>
<input type="text" id="title" name="title" required><br>
<label for="author">Author:</label><br>
<input type="text" id="author" name="author" required><br>
<label for="year">Year:</label><br>
<input type="number" id="year" name="year" required><br>
<p>
<button id="addbook">Add book</button>
<button id="showbooks">Show books added</button>
</p>
Related
I would like my program to automatically select all checkboxes (Specifically "Side 1, Side 2, Side 3 and Side 4") if the wall_amount input is above 3. How would this be done?
I have tried this on javascript lines 10-12. Thanks
HTML
<label for="wall_amount">Number of Walls</label>
<input type="number" value="1" min="1" max="4" step="1" id="wall_amount" name="wall_amount"></input>
<div>
Please choose where you want the walls placed
<label for="wall_side1">Side 1</label>
<input type="checkbox" id="wall_side1" name="wall_side1"></input>
<div style="display: inlineblock;">
<label for="wall_side2">Side 2</label>
<input type="checkbox" id="wall_side2" name="wall_side2"></input>
<img class="img2" src="images/reference.png" alt="Bouncy Castle">
<label for="wall_side3">Side 3</label>
<input type="checkbox" id="wall_side3" name="wall_side3"></input>
</div>
<label for="wall_side4">Side 4</label>
<input type="checkbox" id="wall_side4" name="wall_side4"></input>
</div>
Javascript
var base_length = Number(document.getElementById("base_length").value);
var base_width = Number(document.getElementById("base_width").value);
var walltype = Number(document.getElementById("walltype").value);
var checkbox_side1 = document.getElementById("wall_side1");
var checkbox_side2 = document.getElementById("wall_side2");
var checkbox_side3 = document.getElementById("wall_side3");
var checkbox_side4 = document.getElementById("wall_side4");
var wall_amount = Number(document.getElementById("wall_amount").value);
$("input:checkbox").click(function() {
let max = $("#wall_amount").val();
var bol = $("input:checkbox:checked").length >= max;
$("input:checkbox").not(":checked").attr("disabled", bol);
});
$("wall_amount").on('keyup', function () {
$('checkbox_side1').prop('checked', +$(this).val() > 3);
});
You can use the function setAttribute to check checkboxes. For example, this code (based on your example) will check your element with the id wall_side1.
checkbox_side1.setAttribute("checked", true)
Anyway, try adding this to your code as a function. Then add a conditional statement that runs the function every time your variable exceeds a certain amount.
I am still relatively new at answering questions so I hope this helps!
const checkboxes = [
"wall_side1",
"wall_side2",
"wall_side3",
"wall_side4"
].map((id) => document.getElementById(id));
const amountInput = document.getElementById("wall_amount");
amountInput.addEventListener("change", (event) => {
const value = parseInt(event.target.value || 0);
if (value === 4) {
checkboxes.forEach(
checkbox => {
checkbox.disabled = true;
checkbox.checked = true;
}
);
} else {
checkboxes.forEach(
checkbox => {
checkbox.disabled = false;
}
);
}
});
My code below selects forms with both POST and GET methods. But I want to select forms with GET form method attribute only. How can I use selector/filters to retrieve only those form elements that set form method as GET
const jsdom = require('jsdom');
const { JSDOM } = jsdom;
{
const {
document
} = (new JSDOM(data)).window;
var all = document.getElementsByTagName("FORM");
for (var i = 0, max = all.length; i < max; i++) {
var aform = document.getElementsByTagName("FORM")[i];
// log aform.outerHTML
}
}
You can use querySelectorAll to match more complex rules than just the element type.
A type selector can filter by forms, then attribute selectors can examine the method attribute.
You need to be careful because GET is the default value so you need to test for the case where there is no method attribute at all (with a :not() pseudo-class) and where it is set to GET
const get_forms = document.querySelectorAll("form:not([method]), form[method='get']")
console.log(get_forms.length + " matching forms");
<form method="GET"></form>
<form method="POST"></form>
<form></form>
CSS Selectors
Document.querySelectorAll()
let getform = document.querySelectorAll("form[method=GET]")[0].id;
console.log(getform)
let postform = document.querySelectorAll("form[method=POST]")[0].id;
console.log(postform)
let omittedform = document.querySelectorAll("form")[2];
if (!omitted.getAttribute("method")) {
console.log(omitted.id)
}
[...document.querySelectorAll("form")].forEach(form => {
if (!form.getAttribute("method") || form.getAttribute("method") === "GET") {
console.log("Form with id " + form.id + "is GET")
} else if (form.getAttribute("method") === "POST") {
console.log("Form with id " + form.id + "is POST")
}
});
<form method="GET" id="get">
<label for="fname">First name:</label><br>
<input type="text" id="fname" name="fname"><br>
<label for="lname">Last name:</label><br>
<input type="text" id="lname" name="lname">
</form>
<form method="POST" id="post">
<label for="fname">First name:</label><br>
<input type="text" id="fname" name="fname"><br>
<label for="lname">Last name:</label><br>
<input type="text" id="lname" name="lname">
</form>
<form id="omitted">
<label for="fname">First name:</label><br>
<input type="text" id="fname" name="fname"><br>
<label for="lname">Last name:</label><br>
<input type="text" id="lname" name="lname">
</form>
And as comment suggested, if form method is omitted you would need to check if method attribute exists in HTML, if not, you can treat it as GET.
!omitted.getAttribute("method")
As we don't see your HTML, you would need use examples above to write your own logic suitable for your use case.
Or you can check it all like this:
[...document.querySelectorAll("form")].forEach(form => {
if (!form.getAttribute("method") || form.getAttribute("method") === "GET" ) {
console.log("Form with id " + form.id + "is GET")
} else {
console.log("Form with id " + form.id + "is POST")
}
});
You can do it with javascript variable for which switch between form methods
let formMethod = undefined
let getForms = document.querySelectorAll(`form[method=${formMethod || 'GET'}]`)
formMethod = "POST"
let postForms = let forms = document.querySelectorAll(`form[method=${formMethod || 'GET'}]`)
you can do it also with a function
function findForms(method) {
return document.querySelectorAll(`form[method=${method || 'GET'}]`)
}
let postForms = getForms("POST")
let getForms = getForms("GET")
let firstGetForm = getForms[0]
let firstGetFormId = firstGetForm.id
let secondGetForm = getForms[1]
let secondGetFormId = secondGetForm.id
Here i am using js text to speech with SpeechSynthesis and its working fine with limited amount of words/sentences, but the time i add all my blog paragraph which is more then 2-3k words its not working, its converting till some part and automatically being stop. So how can i add unlimited no of words or total page content converted to speech.
NOTE: I tried js speak() also, which worked fine but i want a pause/stop option so i used this. So if there any other working way then please suggest.
const msg = new SpeechSynthesisUtterance();
let voices = [];
const voicesDropdown = document.querySelector('[name="voice"]');
const options = document.querySelectorAll('[type="range"],[name="text"]');
const speakButton = document.querySelector('#speak');
const stopButton = document.querySelector('#stop');
msg.text = document.querySelector('[name="text"]').value;
function populateVoices() {
voices = this.getVoices();
voicesDropdown.innerHTML = voices.map(voice => `<option value="${voice.name}">${voice.name}(${voice.lang})</option>`).join('');
}
function setVoice() {
msg.voice = voices.find(voice => voice.name === this.value);
toggle();
}
function toggle(startOver = true) { //true is for it will not stop if language changes
speechSynthesis.cancel();
if (startOver) {
speechSynthesis.speak(msg);
}
}
function setOption() {
// console.log(this.name, this.value);
msg[this.name] = this.value;
toggle();
}
speechSynthesis.addEventListener('voiceschanged', populateVoices);
voicesDropdown.addEventListener('change', setVoice);
options.forEach(option => option.addEventListener('change', setOption));
speakButton.addEventListener('click', toggle);
<div class="voiceinator">
<select name="voice" id="voices">
<option value="">Select a voice</option>
</select>
<label for="rate">Rate:</label>
<input type="range" name="rate" min="0" max="3" value="1" step="0.1">
<label for="pitch">Pitch:</label>
<input type="range" name="pitch" min="0" max="2" value="1" step="0.1">
<textarea name="text"></textarea>
<button id="stop">Stop!</button>
<button id="speak">Speak</button>
</div>
It's a known bug. The workaround is to issue a resume every 14 seconds.
You can add this immediately after the line speechSynthesis.speak(msg):
let r = setInterval(() => {
console.log(speechSynthesis.speaking);
if (!speechSynthesis.speaking) {
clearInterval(r);
} else {
speechSynthesis.resume();
}
}, 14000);
I have three inputs which will be given by the user and i want these 3 inputs to make up objects in an array in my javascript file, i.e, the values for these 3 inputs will make up each object in thearray, everytime the user inputs the 3 values and clicks enter, a new object with those 3 values as properties should be added into the array. How do i achieve this?
I have tried to get the values, and onclick to push them into the array but i keep get a "Cannot access 'arr_items' before initialization
at addName"
let input2 = document.getElementById("itemName");
let input3 = document.getElementById("itemWeight");
let input4 = document.getElementById("itemValue");
const arr_items = [];
let i = 0;
function addValues() {
arr_items[i].name.push(input2.value);
arr_items[i].weight.push(input3.value);
arr_items[i].value.push(input4.value);
i++;
}
<div>
<p>Items Information:</p>
<input id="itemName" type="text" placeholder="enter item name">
<button onclick="addValues()" id="name">Enter</button>
<input id="itemWeight" type="number" placeholder="enter item weight(kg)">
<input id="itemValue" type="number" placeholder="enter item value">
</div>
I expect everytime the user inputs the 3 values and clicks enter, a new object with those 3 values as properties should be added into the array.
You are trying to call the property name, weight etc on the array element using .. This is wrong. Try do:
let input2 = document.getElementById("itemName");
let input3 = document.getElementById("itemWeight");
let input4 = document.getElementById("itemValue");
const arr_items = [];
let i = 0;
function addValues() {
arr_items[i] = {
name: input2.value,
weight: input3.value,
value: input4.value
};
i++;
console.log(arr_items)
}
<div>
<p>Items Information:</p>
<input id="itemName" type="text" placeholder="enter item name">
<button onclick="addValues()" id="name">Enter</button>
<input id="itemWeight" type="number" placeholder="enter item weight(kg)">
<input id="itemValue" type="number" placeholder="enter item value">
</div>
You were doing it wrongly try this:
const arrayItems = new Array();
function addValues(){
let input2 = document.getElementById("itemName");
let input3 = document.getElementById("itemWeight");
let input4 = document.getElementById("itemValue");
let inputs = {
input1 : input2.value,
input3 : input3.value,
input4 : input4.value
}
arrayItems.push(inputs);
console.log(arrayItems);
}
<div>
<p>Items Information:</p>
<input id="itemName" type="text" placeholder="enter item name">
<input id="itemWeight" type="number" placeholder="enter item weight(kg)">
<input id="itemValue" type="number" placeholder="enter item value">
<button onclick="addValues()" id="name">Enter</button>
</div>
You can just push to array again and again without counter. Like so:
let input2 = document.getElementById("itemName");
let input3 = document.getElementById("itemWeight");
let input4 = document.getElementById("itemValue");
const arr_items = [];
function addValues() {
arr_items.push({name: input2.value, weight: input3.value, value: input4.value});
console.log(arr_items);
}
Here is a small chunk of code, that I stripped down, that takes every input field, within a parent, that has a name attribute and uses those name attribute values as the keys in an object.
If uses the value of the input fields as the values in the object.
This allows the output object to change based on which input fields are in the parent element. If the input element does not have a name then it is not included.
This code can be reused and it always hands back the object needed.
const getEls = srcEl => {
const subs = [...srcEl.querySelectorAll('[name]')];
return subs.reduce((acc, sub) => {
acc[sub.getAttribute('name')] = sub.value;
sub.value = '';
return acc;
}, {});
subs[0].focus();
}
let results = [];
function doIt() {
const srcEl = document.getElementById('container');
const values = getEls(srcEl);
results.push(values);
console.log(JSON.stringify(values,0,20));
}
const btn = document.getElementById('submit');
btn.addEventListener('click', doIt);
const resultsBtn = document.getElementById('show');
resultsBtn.addEventListener('click', () => {
console.log(JSON.stringify(results,0,2));
});
<div id="container">
<p>Items Information:</p>
<input id="itemName" name="name" type="text" placeholder="enter item name"/><br/>
<input id="itemWeight" name="weight" type="number" placeholder="enter item weight(kg)"/><br/>
<input id="itemValue" name="value" type="number" placeholder="enter item value"/><br/>
<button id="submit">Enter</button>
<hr/>
<button id="show">Results</button>
</div>
There are two main aspects to note in the answer. One is that the array should be declared as a variable (not a constant), the other is that you should move the input var code into the function.
I added an alert so that you can see the outcome (wasn't sure if you wanted to allow them to be added without weight etc? This would cause confusion in your storage/retrieval of data.. so I moved the enter button)
Hope this helps
var arr_items = [];
function addValues() {
let input2 = document.getElementById("itemName");
let input3 = document.getElementById("itemWeight");
let input4 = document.getElementById("itemValue");
var item2 = input2.value + " " + input3.value + " " + input4.value;
arr_items.push(item2);
alert( [arr_items]);
}
<div>
<p>Items Information:</p>
<input id="itemName" type="text" name="item" placeholder="enter item name">
<input id="itemWeight" type="number" name="item" placeholder="enter item weight(kg)">
<input id="itemValue" type="number" name="item" placeholder="enter item value">
<button id="name" onclick="addValues()">Enter</button>
</div>
How I can get value from input and store it to the object?
When button is clicked value from the input - should to be stored in the object.
Thank you a lot in advance
var testObject = { 'name': nameOfbook.value,
'author': nameOfauthor.value,
'year': year.value
};
console.log(testObject);
<input type="text" id="nameOfbook" required="" placeholder="Book name" />
<input type="text" id="nameOfauthor" required="" placeholder="Athor name" />
<input type="text" id="year" required="" placeholder="Add year" />
<button id="addder" type="button">StoreEmail</button>
Here's a working JSfiddle for you.
The relevant JS code is here. Using the id tags on your html elements, I got all of the elements and stored them into variables. Next, I added an event listener on your button, and on click, I push the relevant value of each element into your testObject.
var testObject = [];
const button = document.getElementById("addder");
const name = document.getElementById("nameOfbook");
const author = document.getElementById("nameOfauthor");
const year = document.getElementById("year");
button.addEventListener("click", function() {
testObject.push({
name: name.value,
author: author.value,
year: year.value
})
console.log(testObject)
})
https://jsfiddle.net/991jqomq/
Here's how I did it
HTML:
<form id="new-post">
<label for="post-title">Title:</label>
<input id="post-title" type="text" />
<label for="post-body">Body:</label>
<textarea id="post-body"></textarea>
<button>Post</button>
</form>
JS:
document.getElementById("new-post").addEventListener("submit", function(e) {
e.preventDefault()
const postTitle = document.getElementById("post-title").value
const postBody = document.getElementById("post-body").value
const data = {
title: postTitle,
body: postBody
}
console.log(data)
})