I've been learning JavaScript for only one week so please be gentle! Tried searching for an answer but no luck.
I am writing a names generator and I want the user to click on a button "girlButton" to see a random girl name, same with boys. The problem is that it is generating one name for each button and to see another name, I need to refresh the page. I want to be able to smash the buttons and see a different name every time. I am pretty sure it's something basic, but I am stuck so please could you help? :) I am not pasting Arrays because they are pretty long. Thanks!
const girlsNamesArray = girlsNames.split(' ');
console.log(girlsNamesArray);
const boysNamesArray = boysNames.split(' ');
console.log(boysNamesArray);
let randomGirl = girlsNamesArray[Math.floor(Math.random() * girlsNamesArray.length)];
const girlButton = document.querySelector('.names__button--girl');
let randomBoy = boysNamesArray[Math.floor(Math.random() * boysNamesArray.length)];
const boyButton = document.querySelector('.names__button--boy');
let proposedName = document.querySelector('.names__idea');
girlButton.addEventListener('click', e => proposedName.innerText = `Nazwij córkę ${randomGirl.slice(0, -1)}`);
boyButton.addEventListener('click', e => proposedName.innerText = `Nazwij syna ${randomBoy.slice(0, -1)}`);
I want to be able to hit buttons multiple times and see different values from the array.
Please try with following code block
const girlsNamesArray = girlsNames.split(' ');
console.log(girlsNamesArray);
const boysNamesArray = boysNames.split(' ');
console.log(boysNamesArray);
const girlButton = document.querySelector('.names__button--girl');
const boyButton = document.querySelector('.names__button--boy');
let proposedName = document.querySelector('.names__idea');
girlButton.addEventListener('click', e => {
const string = girlsNamesArray[Math.floor(Math.random() * girlsNamesArray.length)];
proposedName.innerText = `Nazwij córkę ${string}`
});
boyButton.addEventListener('click', e => {
const string = boysNamesArray[Math.floor(Math.random() * boysNamesArray.length)];
proposedName.innerText = `Nazwij syna ${string}`
});
Here you have to write the logic of random inside the event binding.
When a button is clicked, all it does right now is set the innerText of the proposedName element. It doesn't run the random number generator again. So you need to group the code to re-run it:
let girlsNames = "gloriax deborahx fayex"
let boysNames = "jackx petex stefanx"
const girlsNamesArray = girlsNames.split(' ');
console.log(girlsNamesArray);
const boysNamesArray = boysNames.split(' ');
console.log(boysNamesArray);
let randomGirl;
const girlButton = document.querySelector('.names__button--girl');
let randomBoy;
const boyButton = document.querySelector('.names__button--boy');
let proposedName = document.querySelector('.names__idea');
function selectNewNames() {
randomBoy = boysNamesArray[Math.floor(Math.random() * boysNamesArray.length)];
randomGirl = girlsNamesArray[Math.floor(Math.random() * girlsNamesArray.length)];
}
girlButton.addEventListener('click', e => {selectNewNames(); proposedName.innerText = `Nazwij córkę ${randomGirl.slice(0, -1)}`});
boyButton.addEventListener('click', e => {selectNewNames(); proposedName.innerText = `Nazwij syna ${randomBoy.slice(0, -1)}`});
<button type="button" class="names__button--girl">New girl</button>
<button type="button" class="names__button--boy">New boy</button>
<h2 class="names__idea"></h2>
Firstly all the best for your journey.To achieve this, you can move the logic for generating random names inside the event listeners so that every time the button is clicked, a new random name is generated .The code for the same will be something like this.
const girlButton = document.querySelector('.names__button--girl');
const boyButton = document.querySelector('.names__button--boy');
const randomIndex = (arr) = >{
return Math.floor(Math.random() * arr.length);
}
girlButton.addEventListener('click', e = >{
let randomGirl = girlsNamesArray[randomIndex(girlsNamesArray)];
proposedName.innerText = `Nazwij córkę$ {
randomGirl.slice(0, -1)
}`;
});
boyButton.addEventListener('click', e = >{
let randomBoy = boysNamesArray[randomIndex(boysNamesArray)];
proposedName.innerText = `Nazwij syna $ {
randomBoy.slice(0, -1)
}`;
});
`
Related
I got this these values.
And I want to have this result.
So I made the following test code and tried it to the first cell.
function test2() {
const ss = SpreadsheetApp.getActive();
const sheet = ss.getSheetByName("richText3");
const range1 = sheet.getRange("A1");
const text1 = range1.getValue();
Logger.log(text1);
const re = new RegExp(/\([ a-zA-Z\/']*\)\?/dg);
const redBold = SpreadsheetApp.newTextStyle().setBold(true).setForegroundColor('red').build();
let array;
while ((array = re.exec(text1)) !== null) {
const [start, end] = array.indices[0];
const richTxtValBlder = SpreadsheetApp.newRichTextValue()
.setText(text1)
.setTextStyle(start, end, redBold)
.build();
range1.setRichTextValue(richTxtValBlder);
}
}
After first try, I got this result.
I checked the Reference Document again and I found this comment.
setText(text) : Sets the text for this value and clears any existing text style.
When creating a new Rich Text value, this should be called before setTextStyle()
I found that I should call .setText() once and call .setTextStyle() multiple times.
But the problem is .setTextStyle() should be called programmatically according to the number of patterns in each cell and I cannot find how to do it programmatically.
Each cell may have 0 to 10 patterns and I don't want to make 10 different richTExtValueBuilder which only differ in the number of .setTextStyle() calls.
Do you have any different ideas ?
Modification points:
In your script, only cell "A1" is used, and also the 1st match is used. I thought that this might be the reason for your issue.
In order to achieve your goal, I retrieve the values from column "A". And also, I use matchAll instead of exec.
When these points are reflected in your script, how about the following modification?
Modified script:
function test2() {
const ss = SpreadsheetApp.getActive();
const sheet = ss.getSheetByName("richText3");
const range1 = sheet.getRange("A1:A" + sheet.getLastRow());
const re = new RegExp(/\([ a-zA-Z\/']*\)\?/g);
const redBold = SpreadsheetApp.newTextStyle().setBold(true).setForegroundColor('red').build();
const richTextValues = range1.getRichTextValues();
const res = richTextValues.map(([a]) => {
const array = [...a.getText().matchAll(re)];
if (array) {
const temp = a.copy();
array.forEach(a => temp.setTextStyle(a.index, a.index + a[0].length, redBold));
return [temp.build()];
}
return [a];
});
range1.setRichTextValues(res);
}
Testing:
When this script is run, the following result is obtained.
From:
To:
References:
map()
setRichTextValues(values)
It looks like you need to call .setText() once, .setTextStyle() multiple times, and .build() once, e.g. change your while loop. Untested code:
let richTxtValBlder = SpreadsheetApp.newRichTextValue().setText(text1);
while ((array = re.exec(text1)) !== null) {
const [start, end] = array.indices[0];
richTxtValBlder = richTxtValBlder.setTextStyle(start, end, redBold);
}
richTxtValBlder = richTxtValBlder.build();
range1.setRichTextValue(richTxtValBlder);
I watched a tutorial on how to use Javascript with Autocomplete using a JSON file and Fetch. Everything works fine; except for the following:
If I clear the input, it shows all of the results in the file. I have included a comment in the code where I try to clear the results but it doesn't work.
The example on JSFiddle doesn't work because I can't add any assets.
Here is the code that should be clearing the data when no characters are in the input box:
if (matches.length === 0) {
matchList.innerHTML = ''; // Line 31: This doesn't clear the results when no input is entered.
}
But in the CSS field, I have hard coded some of the JSON file for your reference.
Thanks in advance,
Matt
using onChange() you can check final length of the keyword written in input tag, and for NULL you can just ignore the suggestion.
I played around with the code and researched it. I had to separate the code into two events. The one that was missing was when the DOM is loaded, then grab a list of states. Here is the revised code:
const search = document.getElementById('search');
const matchList = document.getElementById('match-list');
let states;
// Get states
const getStates = async () => {
const res = await fetch('states.json');
states = await res.json();
};
// FIlter states
const searchStates = (searchText) => {
// Get matches to current text input
let matches = states.filter((state) => {
const regex = new RegExp(`^${searchText}`, 'gi');
return state.name.match(regex) || state.abbr.match(regex);
});
// Clear when input or matches are empty
if (searchText.length === 0) {
matches = [];
matchList.innerHTML = '';
}
outputHtml(matches);
};
// Show results in HTML
const outputHtml = (matches) => {
if (matches.length > 0) {
const html = matches
.map(
(matt) => `<div class="card card-body mb-1">
<h4>${matt.name} (${matt.abbr})
<span class="text-primary">${matt.capital}</span></h4>
<small>Lat: ${matt.lat} / Long: ${matt.long}</small>
</div>`
)
.join('');
matchList.innerHTML = html;
}
};
window.addEventListener('DOMContentLoaded', getStates);
search.addEventListener('input', () => searchStates(search.value));
If the value is exist in localstorage I want to replace it. When I try to do that existing value is still inserting.
addEntry = (e,id) => {
e.preventDefault()
let product_list = []
let productCost = document.getElementById('projectcost').value;
let productQty = document.getElementById('productQty'+id).value;
let productId = id;
if(localStorage.getItem('myItems')){
product_list = JSON.parse(localStorage.getItem('myItems'))
product_list.push({productId,productCost,productQty})
localStorage.setItem('myItems',JSON.stringify(product_list))
}else{
product_list.push({productId,productCost,productQty})
localStorage.setItem('myItems',JSON.stringify([{productId,productCost,productQty}]))
}
}
Output
[{"productId":43,"productCost":"320","productQty":"2"},{"productId":43,"productCost":"480","productQty":"3"},{"productId":44,"productCost":"420","productQty":"3"}]
When I want to insert same value I want the output to be
[{"productId":43,"productCost":"480","productQty":"3"},{"productId":44,"productCost":"420","productQty":"3"}]
To avoid that you push the same product a second time, first filter out the object that might concern the same product:
let productCost = +document.getElementById('projectcost').value;
let productQty = +document.getElementById('productQty'+id).value;
let product_list = JSON.parse(localStorage.getItem('myItems') ?? "[]");
.filter(({productId}) => productId != id)
.concat({productId: id, productCost, productQty});
localStorage.setItem('myItems', JSON.stringify(product_list));
I am practicing blog stuff. posting and deleting posts. mini social media I can say. And I wanted to save posts on localStorge. however I could save only 1 post at a time. and then I wanted to do it with IDs.
I create id with random number generator:
let newId = Math.floor(Math.random() * (1000000 - 100000) + 100000)
let postContents = {
ID : newId,
text: value,
}
an then I upload those values in let storedPosts = [] array.
then I save it to local storage with JSON:
let toJson = () => {
localStorage.setItem('storedPosts', JSON.stringify(storedPosts));
}
and then I get it from Local Storage:
let storedJsonPosts = localStorage.getItem('storedPosts')
let storedPosts_toUpload = JSON.parse(storedJsonPosts)
and then I join these two arrays together:
let storedPostsArray = storedPosts.concat(storedPosts_toUpload)
and after this I don't know what to do. I tried this:
let uploadStoredPosts = () => {
for (let i = 0; i < storedPostsArray.length; i++) {
let post = document.createElement('div')
$post_place.appendChild(post)
let text = document.createElement('p')
post.appendChild(text)
text.textContent = storedPostsArray[i].text
}
}
but it showed this:
It couldn't reach array values. plz help
Is this something that you're after?
The code reads from localStorage, parses that information, returns an empty array if it's the first time the user posted, pushes a new value to the array, stores that array by stringifying it, and the appending the new value to the document.
If you want the page to read from localStorage on page load, you need to add a function that reads from localStorage, and then loops through all posts to add each one of them by using appendToDocument().
StackOverflow doesn't allow the use of localStorage, so I used a variable for demo purposes.
I left out id as a property. You can play around with that by yourself, but I would suggest to use a timestamp as a foreign key ("id").
var justForDemoPurpose = null;
const addPostBtn = document.getElementById("add-button");
const addPostInput = document.getElementById("add-post");
const postContainerEl = document.getElementById("post-container");
addPostBtn.addEventListener('click', addPost);
function readFromLocalStorage(key) {
let localStorageItem = JSON.parse(justForDemoPurpose);
// let localStorageItem = JSON.parse(localStorage.getItem(key));
console.log('returning items:', localStorageItem);
return localStorageItem;
}
function storeInLocalStorage(key, value) {
justForDemoPurpose = JSON.stringify(value);
// JSON.stringify(localStorage.setItem(key, value));
}
function addPost() {
let postValue = addPostInput.value;
if (postValue) {
const LOCAL_STORAGE_KEY = 'posts';
let storedPosts = readFromLocalStorage(LOCAL_STORAGE_KEY) || [];
storedPosts.push(postValue);
storeInLocalStorage(LOCAL_STORAGE_KEY, storedPosts);
appendToDocument(postValue);
}
}
function appendToDocument(postValue) {
let divEl = document.createElement('div')
divEl.textContent = postValue;
postContainerEl.appendChild(divEl);
}
<div class="addPostContainer">
<input id="add-post" placeholder="Type here"> <button id="add-button">Add Post</button>
</div>
<section id="post-container"></section>
English is not my language so there might be mistakes, i'm beginner programmer(react hooks), my form(antd) data is moving in url, everything is working fine except going back and changing form input value to another then going again forward, i can see there is now two times same key but different value, my point is now there is for example 'name=james' and 'name=susan', but i want to have just one 'name' and it should be the latest, should i be pushing differently? below is also a picture i made about this, if it helps to understand. when console.log(query); it shows both 'names'
Next page function comes from here :
< Form onFinish={nextPage}>
< / Form>
i'm going back from page b to page a like this:
const query = window.location.toString().split("?")[1];
const handleclick = () => {
history.push(`/pagea/${custId}?${query}`);
};
history push in nextPage function is like this
const query = window.location.toString().split("?")[1];
const nextPage = (order: rRequest) => {
history.push(`/customers/${custId}?${query}&name=${order.name}`);
};
const query = window.location.toString().split("?")[1];
var qry = "";
if (query) {
qry = query.split("&");
for (var i = 0; i < qry.length; i++) {
var curr = qry[i].split("=");
if (curr[0] == "name") {
qry.splice(i, 1);
i--;
}
}
qry = qry.join("&");
}
const nextPage = (order: rRequest) => {
history.push(`/customers/${custId}?${qry}&name=${order.name}`);
};