How to make the button extract text from othere elements? - javascript

I have made a small "Note Taker" application for educational purposes, and I want to add one more functionality there. I want the "View Detail" button to show the whole note in a modal appearing in the middle of the screen, but I'm not actually sure how I am supposed to do this and how to make the button extract the text from the initial note.
I attach html, javascript code and a screenshot for better understanding of the problem.
<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="/style.css">
<script src="/app.js" defer></script>
<title>Document</title>
</head>
<body>
<h1>Note Taker</h1>
<h2>Add A New Note:</h2>
<div id="inputField">
<p id="note">Note:</p>
<textarea name="" id="textField" cols="30" rows="10" placeholder="Put your text here"></textarea>
</div>
<button id="addNoteBtn">Add Note</button>
<div id="noteContainer">
</div>
</body>
</html>
HTML here ^
const addNoteBtn = document.getElementById("addNoteBtn")
const noteContainer = document.getElementById("noteContainer")
addNoteBtn.addEventListener("click", renderHTML)
window.addEventListener("DOMContentLoaded", callStorage)
function renderHTML(){
const noteBox = document.createElement("div")
noteBox.classList.add("noteBox")
const noteTitle = document.createElement("h3")
const noteText = document.createElement("p")
const insideNoteBtn = document.createElement("button")
insideNoteBtn.classList.add("insideNoteBtn")
noteContainer.appendChild(noteBox)
noteBox.appendChild(noteTitle)
noteBox.appendChild(noteText)
noteBox.appendChild(insideNoteBtn)
let noteStorage
if(localStorage.getItem("notes")=== null){
noteStorage = []
}else{
noteStorage = JSON.parse(localStorage.getItem("notes"))
}
noteStorage.push(textfield.value)
localStorage.setItem("notes", JSON.stringify(noteStorage))
noteStorage.forEach(function(value, index){
noteTitle.textContent = `Note ${index + 1}`
noteText.textContent = value
insideNoteBtn.textContent = "View Detail"
})
}
function callStorage(){
let noteStorage
if(localStorage.getItem("notes")=== null){
noteStorage = []
}else{
noteStorage = JSON.parse(localStorage.getItem("notes"))
}
noteStorage.forEach(function(value, index){
const noteBox = document.createElement("div")
noteBox.classList.add("noteBox")
const noteTitle = document.createElement("h3")
const noteText = document.createElement("p")
const insideNoteBtn = document.createElement("button")
insideNoteBtn.classList.add("insideNoteBtn")
noteContainer.appendChild(noteBox)
noteBox.appendChild(noteTitle)
noteBox.appendChild(noteText)
noteBox.appendChild(insideNoteBtn)
noteTitle.textContent = `Note ${index + 1}`
noteText.textContent = value
insideNoteBtn.textContent = "View Detail"
})
}
Javascript here ^
screenshot ^

Related

Openweather API linking the searchbar to the actual city chosen from the hard coding part

I am currently working on a weather app using Openweather API, and I'm having a little strugle on creating the function that in the moment that a city is written in the search bar and the button search is pressed, I want the h1 with the class "chosen-location" textcontent to change into the input from the search bar, this thing should happen by changing the value of the variable city into the content from the searchbar. That's how I would do it if I would have some more expierence, but I don't know how to really write all this stuff.
const apikey = `45d2b1974108dfa1128c4ce9991a1f56`;
let city = "Constanta";
let search = document.querySelector('.searchbar');
let button = document.querySelector('.btn');
window.addEventListener('load', ()=>{
let long;
let lat;
let temperatureDescription = document.querySelector('.temperature-description');
let temperatureDegree = document.querySelector('.degree');
let locationTimezone = document.querySelector('.location-timezone');
let icon = document.querySelector('.icon');
if(navigator.geolocation){
navigator.geolocation.getCurrentPosition(position => {
long = position.coords.longitude;
lat = position.coords.latitude;
// what i've done here takes your coordinates and puts them to the variables mentioned
const api = `https://api.openweathermap.org/data/2.5/weather?q=${city}&APPID=${apikey}&units=metric`;
fetch(api)
.then(respones => {
return respones.json();
})
.then(data =>{
console.log(data);
const {temp} = data.main;
const {main} = data.weather[0];
const {country} = data.sys;
// set DOM elements from the API
temperatureDegree.textContent = temp;
temperatureDescription.textContent = main;
locationTimezone.textContent = country;
if(temperatureDescription.textContent === 'Mist'){
document.querySelector('.icon').src='http://openweathermap.org/img/wn/50d#2x.png';
}if(temperatureDescription.textContent === 'Clear Sky'){
document.querySelector('.icon').src='http://openweathermap.org/img/wn/01d#2x.png';
}if(temperatureDescription.textContent === 'Clouds'){
document.querySelector('.icon').src='http://openweathermap.org/img/wn/03d#2x.png';
}if(temperatureDescription.textContent === 'Rain'){
document.querySelector('.icon').src='http://openweathermap.org/img/wn/10d#2x.png';
}if(temperatureDescription.textContent === 'Thunderstorm'){
document.querySelector('.icon').src='http://openweathermap.org/img/wn/11d#2x.png';
}if(temperatureDescription.textContent === 'Snow'){
document.querySelector('.icon').src='http://openweathermap.org/img/wn/13d#2x.png';
}
console.log(temperatureDescription.textContent);
});});
}
});
<!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> Weather app </title>
</head>
<body>
<div class="location">
<h1 class="location-timezone">Timezone</h1>
<h1 class="chosen-location">Constanta</h1>
<img class= "icon" src="http://openweathermap.org/img/wn/01d#2x.png" alt="weather">
</div>
<div class="search"><input type="text" placeholder="Ex:Chicago" class="searchbar"></div> <button class="btn">Search</button>
<div class="temperature">
<div class="degree-section">
<h2 class="degree">34</h2>
<span> Celsius</span>
</div>
<div class="temperature-description">It's frkin cold</div>
</div>
<script type ="module" src="script.js"></script>
</body>
</html>

Why isnt my button displaying value onto the div

I want the button with the id of number1 to display the value of 1 on to the input box which has the id of quest which is short for question.I also want to know if my code can be made more readable.
<!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>Calucator</title>
<style>
body{
text-align: center;
}
</style>
<script>
const quest = document.getElementById("quest");
const data = quest.value;
const yourElement = document.createElement("div");
function nums(){
const num1 = document.getElementById('number1').innerText = 1;
data.textContent = num1;
}
function run() {
nums()
yourElement.textContent = data
quest.appendChild(yourElement);
}
</script>
</head>
<body>
<h1>Calucator</h1>
<input type="number" placeholder="Enter now" name="" id="quest">
<button onclick="run()">=</button>
<br>
<button onclick="" id="number1">1</button>
</body>
</html>
<script>
const quest = document.getElementById("quest");
const data = quest.value;
const yourElement = document.createElement("div");
//PROBLEM 1: You are not attaching yourElement to the DOM. See Element.insertBefore / Element.appendChild
function nums(){
const num1 = document.getElementById('number1').innerText = 1;
data.textContent = num1;
}
function run() {
nums()
yourElement.textContent = data
quest.appendChild(yourElement);
}
</script>
And
<button onclick="run()">=</button>
Problem 2: Don't use inline element event handling. It isn't safe and Content-Security-Policy won't allow it. Instead, use JavaScript Element.addEventListener(...)

is there a way to assign id or classname to an element through document.createElement?

Im still relatively new to JS. I know i probably shouldnt write my code the way i have done here in the real world, but im only doing this to test my knowledge on for loops and pulling JSON data.
My question is, with the way i have structured my code, is it possible for me to add classnames/Id's to the elements i have made using doc.createElement? for example if i wanted to add custom icons or buttons to each element? I cant seem to think of a way to add them other than having to write out all the HTML and do it that way. Here's my code :
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="./styles.css">
<title>Document</title>
</head>
<body>
<section>
</section>
<script src="./app.js"></script>
</body>
</html>
JS
const allCustomers = document.querySelector("section");
let custName = "";
let username = "";
let email = "";
let id = "";
const requestURL = "https://jsonplaceholder.typicode.com/users";
fetch(requestURL)
.then((response) => response.text())
.then((text) => DisplayUserInfo(text));
function DisplayUserInfo(userData) {
const userArray = JSON.parse(userData);
for (i = 0; i < userArray.length; i++) {
let listContainer = document.createElement("div");
let myList = document.createElement("p");
let myListItems = document.createElement("span");
myList.textContent = `Customer : ${userArray[i].name}`;
myListItems.innerHTML =`<br>ID: ${userArray[i].id} <br>Email: ${userArray[i].email} <br>Username: ${userArray[i].username}`;
myListItems.appendChild(myList);
listContainer.appendChild(myListItems);
allCustomers.appendChild(listContainer);
}
}
DisplayUserInfo();
Any pointers would be greatly appreciated as well as any constructive feedback. Thanks
Yes, for sure you can add any attribute for a created element. element.classList.add('class-name-here') for adding class, element.id = 'id-name-here' for adding id.
const allCustomers = document.querySelector("section");
let custName = "";
let username = "";
let email = "";
let id = "";
const requestURL = "https://jsonplaceholder.typicode.com/users";
fetch(requestURL)
.then((response) => response.text())
.then((text) => DisplayUserInfo(text));
function DisplayUserInfo(userData) {
const userArray = JSON.parse(userData);
for (i = 0; i < userArray.length; i++) {
let listContainer = document.createElement("div");
let myList = document.createElement("p");
myList.classList.add('active');
myList.id = 'paragraph'
let myListItems = document.createElement("span");
myList.textContent = `Customer : ${userArray[i].name}`;
myListItems.innerHTML =`<br>ID: ${userArray[i].id} <br>Email: ${userArray[i].email} <br>Username: ${userArray[i].username}`;
myListItems.appendChild(myList);
listContainer.appendChild(myListItems);
allCustomers.appendChild(listContainer);
}
}
DisplayUserInfo();
.active {
color: red;
}
#paragraph {
font-size: 24px;
}
<!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>Document</title>
</head>
<body>
<section>
</section>
<script src="./app.js"></script>
</body>
</html>
is it possible for me to add classnames/Id's to the elements i have
made using doc.createElement
Yes possible with classList for adding class and setAttribute to add id
let listContainer = document.createElement("div");
// To add class
listContainer.className = 'your-class'; //if you have just one
listContainer.classList.add("my-class");//if you want to add multiple
// To add id
listContainer.setAttribute("id", "your_id");
When you use document.createElement it returns an Element. You can use Element attributes and methods to reach what you need. There are some docs for this class on MDN.
This means you can:
> myDiv = document.createElement("div")
<div></div>
> myDiv.id = "test"
'test'
> myDiv
<div id="test"></div>
For classes you can use the attributes className or classList.

How to create a form for comments with the ability of dynamically adding them to the list?

I need to create a form for comments with the ability to dynamically add them to the list. Each comment should have an assigned ID in consecutive order. The newest comment should be at the very bottom. Comments should be stored in the comments array. Each comment should have properties such as id (number) and text (string). Comments array must be empty when loaded initially. Each click on the "Add" button should create a new object inside the array and create element in the DOM tree.
let nextId = 1;
const comments = [];
const commentForm = document.querySelector('[data-id="comment-form"]');
const commentInput = commentForm.querySelector('[data-input="comment"]');
const button = commentForm.querySelector('[data-action="add"]');
const commentList = commentForm.querySelector('[data-id="comment-list"]');
button.addEventListener('click', () => {
const object = {};
if (commentInput.value != '') {
comments.map(() => ({ id: 'nextId++', text: commentInput.value }));
}
createElement();
});
function createElement() {
const newComment = document.createElement('li');
newComment.setAttribute('data-comment-id', comments.id);
newComment.textContent = comments.text;
commentList.appendChild(newComment);
}
<!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></title>
<link rel="stylesheet" href="./css/styles.css" />
</head>
<body>
<div id="root">
<form data-id="comment-form">
<textarea data-input="comment"></textarea>
<button data-action="add">Add</button>
</form>
<ul data-id="comment-list"></ul>
</div>
<script src="./js/app.js"></script>
</body>
</html>
There are some issues in your code:
You are trying to access commentList from commentForm, but that element is outside of the commentForm. Use document object to access the element.
comments is an array from which you are trying to access text property, there is text property on comments.
You should pass the current input value to the function so that you can set the newly created LI's text with the value.
You should use push() instead of map() to push an item into the array. nextId is a variable but you are using that as if it is a string, you should remove the quotes around it.
For the better user experience, I will suggest you to clear the value of the input after creating the item.
Demo:
let nextId = 1;
const comments = [];
const commentForm = document.querySelector('[data-id="comment-form"]');
const commentInput = commentForm.querySelector('[data-input="comment"]');
const button = commentForm.querySelector('[data-action="add"]');
const commentList = document.querySelector('[data-id="comment-list"]');
button.addEventListener('click', () => {
const object = {};
if (commentInput.value != '') {
comments.push({ id: nextId++, text: commentInput.value });
}
createElement(commentInput.value);
commentInput.value = '';
});
function createElement(ci) {
const newComment = document.createElement('li');
newComment.setAttribute('data-comment-id', comments.id);
newComment.textContent = ci;
commentList.appendChild(newComment);
}
<!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></title>
<link rel="stylesheet" href="./css/styles.css" />
</head>
<body>
<div id="root">
<form data-id="comment-form">
<textarea data-input="comment"></textarea>
<button type="button" data-action="add">Add</button>
</form>
<ul data-id="comment-list"></ul>
</div>
<script src="./js/app.js"></script>
</body>
</html>

How can I combine two event functions of properties such as JavaScript?

var input = document.querySelector('input');
var button = document.querySelector('button');
var question = document.querySelector('.p1')
var result = document.querySelector('.p2')
button.addEventListener("click",function(e){
e.preventDefault;
question.innerHTML = input.value;
input.value = "";
input.placeholder = question.textContent[question.textContent.length-1]+ " finished word?";
input.focus();
})
/*
button.addEventListener("click",function(ev){
ev.preventDefault;
if(question.textContent[question.textContent.length-1] === input.value[0])
{
question.innerHTML = input.value;
input.value = "";
result.innerHTML = "good"
input.focus();
}
else{
input.value = "";
result.innerHTML = "bad"
input.focus();
}
})
*/
<!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>Document</title>
</head>
<body>
<p class="p1"></p>
<input type="text" placeholder="input first word">
<button type="button">submit</button>
<p class="p2"></p>
<script src="끝말잇기2.js"></script>
</body>
</html>
I am sorry that I asked you a question using a translator because I can't speak English.
I have a question in the JavaScript code.
First, the first function is input the first word, and the event is click.
The second function is the same as the first letter of the word you received, and the last letter is the same, so you put the first letter in the first letter.
These two functions can be combined, but I think both functions are duplicated because they are event clicks.
How can i write code that combines two functions and performs sequential functions?
One Function Solution
There is no need for two functions, you can write it as one function. Consider here that you don't reset the input.value twice when you combine both. Just reset it at the end of the function.
var input = document.querySelector('input');
var button = document.querySelector('button');
var question = document.querySelector('.p1')
var result = document.querySelector('.p2')
button.addEventListener("click", function() {
question.innerHTML = input.value;
input.placeholder = question.textContent[question.textContent.length - 1] + " finished word?";
input.focus();
if (question.textContent[question.textContent.length - 1] === input.value[0]) {
question.innerHTML = input.value;
input.value = "";
result.innerHTML = "good"
input.focus();
} else {
input.value = "";
result.innerHTML = "bad"
input.focus();
}
})
<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>Document</title>
</head>
<body>
<p class="p1"></p>
<input type="text" placeholder="input first word">
<button type="button">submit</button>
<p class="p2"></p>
<script src="끝말잇기2.js"></script>
</body>
</html>
Call Consecutively Wrapper Function
If you want to use two functions you can do a wrapper function and inside it you can call your two other functions.
Then when the button get's pressed you call the wrapper function which will proceed the two other functions consecutively.
var input = document.querySelector('input');
var button = document.querySelector('button');
var question = document.querySelector('.p1')
var result = document.querySelector('.p2')
button.addEventListener("click", wrapperFunction);
function a() {
question.innerHTML = input.value;
input.placeholder = question.textContent[question.textContent.length - 1] + " finished word?";
input.focus();
}
function b() {
if (question.textContent[question.textContent.length - 1] === input.value[0]) {
question.innerHTML = input.value;
input.value = "";
result.innerHTML = "good"
input.focus();
} else {
input.value = "";
result.innerHTML = "bad"
input.focus();
}
}
function wrapperFunction() {
a();
b();
}
<!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>Document</title>
</head>
<body>
<p class="p1"></p>
<input type="text" placeholder="input first word">
<button type="button">submit</button>
<p class="p2"></p>
<script src="끝말잇기2.js"></script>
</body>
</html>
I removed the preventDefault, then I added a setTimeout to changing input.value so both functions can run(with the input.value resource shared)
Because setTimeout is asynchronous, it would work well in situations like this, since it would wait until the other things finish running(I'm paraphrasing so don't quote me) then it will run.. making both functions work at the "same time"
var input = document.querySelector('input');
var button = document.querySelector('button');
var question = document.querySelector('.p1')
var result = document.querySelector('.p2')
button.addEventListener("click",function(e){
//e.preventDefault;
question.innerHTML = input.value;
setTimeout(()=>{input.value = "";},0)
input.placeholder = question.textContent[question.textContent.length-1]+ " finished word?";
input.focus();
})
button.addEventListener("click",function(ev){
//ev.preventDefault;
if(question.textContent[question.textContent.length-1] === input.value[0])
{
question.innerHTML = input.value;
setTimeout(()=>{input.value = "";},0)
result.innerHTML = "good"
input.focus();
}
else{
setTimeout(()=>{input.value = "";},0)
result.innerHTML = "bad"
input.focus();
}
})
<!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>Document</title>
</head>
<body>
<p class="p1"></p>
<input type="text" placeholder="input first word">
<button type="button">submit</button>
<p class="p2"></p>
<script src="끝말잇기2.js"></script>
</body>
</html>

Categories