Changing elements to lowercase issues - javascript

I'm building a dynamic list of trees that starts with Oak, Pine, Aspen, Bald Cypress.
Which includes a button to add a 'Redwood' tree to the end of the list, and a 'Pear' tree to the start of the list.
I then included a button that onclick would change the strings to lowercase but I can't seem to get it right. I know the push() method will add the lowercase strings to the end of the list but I can't figure out how to get rid of the old strings with uppercase letters, and it also keeps adding more items to the list when the button is pushed again. I also tried the map method, however it did not seem to work unless created a new variable.
const trees = ['Oak', 'Pine', 'Aspen', 'Bald Cypress']
const listTrees = () => {
let treeList = ''
trees.forEach(tree => {
//console.log(tree)
treeList += `${tree} <br>`
})
displayResults.innerHTML = `${treeList} <span>${trees.length} elements
long</span>`
}
listTrees()
* ------adding redwood to the end ------------*/
document.querySelector('#add_redwood').onclick = () => {
trees.push('Redwood')
listTrees()
}
/* --------------------adding a pear to the start ----------------------*/
document.querySelector('#add_pear').onclick = () => {
trees.unshift('Pear')
listTrees()
}
document.querySelector('#lowerTrees').onclick = () => {
trees.forEach(tree => {
trees.push(tree.toLowerCase())
})
listTrees()
}

Simply declare trees with let instead of const then reassign it. There is no reason for you to keep the original array reference in this case. Then you can use map(). You can also use map() for listTrees().
const displayResults = document.querySelector("#displayResults");
let trees = ['Oak', 'Pine', 'Aspen', 'Bald Cypress']
const listTrees = () => {
let treeList = trees.map(tree => `${tree}<br>`).join("");
displayResults.innerHTML = `${treeList} <span>${trees.length} elements long</span>`
}
listTrees()
/* ------adding redwood to the end------------ */
document.querySelector('#add_redwood').onclick = () => {
trees.push('Redwood')
listTrees()
}
/* --------------------adding a pear to the start ----------------------*/
document.querySelector('#add_pear').onclick = () => {
trees.unshift('Pear')
listTrees()
}
document.querySelector('#lowerTrees').onclick = () => {
trees = trees.map(tree => tree.toLowerCase());
listTrees();
}
<button id="add_redwood">Add Redwood</button>
<button id="add_pear">Add Pear</button>
<button id="lowerTrees">Lower Trees</button>
<div id="displayResults"></div>
If you really want to keep tree as const, use a regular for loop to change each element one by one instead.
for(let i = 0; i < trees.length; i++)
{
trees[i] = trees[i].toLowerCase();
}

Because you have to reassign lowercased values to HTML
document.querySelector('#lowerTrees').onclick = () => {
trees.forEach(tree => {
trees.push(tree.toLowerCase())
})
listTrees()
}

Related

Problem with sessionStorage: I am not displaying the first item correctly

I am having a problem with sessionStorage; in particular, I want the id of the ads to be saved in the session where the user puts the like on that particular favorite article.
However, I note that the array of objects that is returned contains the ids starting with single quotes, as shown below:
['', '1', '7']
but I want '1' to be shown to me directly.
While if I go into the sessionStorage I notice that like is shown as:
,1,7
ie with the leading comma, but I want it to start with the number directly.
How can I fix this?
function likeAnnunci(){
let likeBtn = document.querySelectorAll('.like');
likeBtn.forEach(btn => {
btn.addEventListener('click', function(){
let id = btn.getAttribute('ann-id');
//sessionStorage.setItem('like', [])
let storage = sessionStorage.getItem('like').split(',');
//console.log(storage);
if(storage.includes(id)){
storage = storage.filter(id_a => id_a != id);
} else {
storage.push(id);
}
sessionStorage.setItem('like', storage)
console.log(sessionStorage.getItem('like').split(','));
btn.classList.toggle('fas');
btn.classList.toggle('far');
btn.classList.toggle('tx-main');
})
})
};
function setLike(id){
if(sessionStorage.getItem('like')){
let storage = sessionStorage.getItem('like').split(',');
if(storage.includes(id.toString())){
return `fas`
} else {
return `far`
}
} else {
sessionStorage.setItem('like', '');
return`far`;
}
}
The main issue you're having is that you're splitting on a , instead of using JSON.parse().
Also, you've got some other code issues and logical errors.
Solution:
function likeAnnunci() {
const likeBtn = document.querySelectorAll('.like');
likeBtn.forEach((btn) => {
btn.addEventListener('click', function () {
let id = btn.getAttribute('ann-id');
//sessionStorage.setItem('like', [])
let storage = JSON.parse(sessionStorage.getItem('like') || '[]');
//console.log(storage);
if (!storage.includes(id)) {
storage.push(id);
}
sessionStorage.setItem('like', JSON.stringify(storage));
console.log(JSON.parse(sessionStorage.getItem('like')));
btn.classList.toggle('fas');
btn.classList.toggle('far');
btn.classList.toggle('tx-main');
});
});
}
More modular and optimal solution:
const likeBtns = document.querySelectorAll('.like');
// If there is no previous array stored, initialize it as an empty array
const initLikesStore = () => {
if (!sessionStorage.getItem('likes')) sessionStorage.setItem('likes', JSON.stringify([]));
};
// Get the item from sessionStorage and parse it into an array
const grabLikesStore = () => JSON.parse(sessionStorage.getItem('likes'));
// Set a new value for the likesStore, automatically serializing the value into a string
const setLikesStore = (array) => sessionStorage.setItem('likes', JSON.stringify(array));
// Pass in a value.
const addToLikesStore = (value) => {
// Grab the current likes state
const pulled = grabStorage();
// If the value is already there, do nothing
if (pulled.includes(value)) return;
// Otherwise, add the value and set the new array
// of the likesStore
storage.push(value);
setLikesStore(pulled);
};
const likeAnnunci = (e) => {
// Grab the ID from the button clicked
const id = e.target.getAttribute('ann-id');
// Pass the ID to be handled by the logic in the
// function above.
addToLikesStore(id);
console.log(grabLikesStore());
btn.classList.toggle('fas');
btn.classList.toggle('far');
btn.classList.toggle('tx-main');
};
// When the dom content loads, initialize the likesStore and
// add all the button event listeners
window.addEventListener('DOMContentLoaded', () => {
initLikesStore();
likeBtns.forEach((btn) => btn.addEventListener('click', likeAnnunci));
});

Unable to get doc id in Firebase

I am trying to get the doc id of each data entry upon click to delete that specific record, but upon checking it is only showing id of the first entry made in the Firebase.
const deleteRecord = () => {
db.collection("records").onSnapshot((querySnapshot) => {
querySnapshot.forEach((doc) => {
// console.log(doc.id)
let recToDel = document.querySelectorAll(".records")
for (let toDelRecord of recToDel) {
toDelRecord.onclick = () => {
console.log(doc.id)
}
}
})
})
}
The loops are nested, so the last iteration of the querySnapshot.forEach loop is the one that sets the same doc.id for every recToDel dom element.
Fix by looping just one collection and indexing into the other...
let recToDel = Array.from(document.querySelectorAll(".records"));
querySnapshot.docs.forEach((doc, index) => {
if (index < recToDel.length) {
let toDelRecord = recToDel[index];
toDelRecord.onclick = () => {
console.log(doc.id)
}
}
});
If there are fewer .records elements than there are docs, some won't be assigned.
Doing this onSnapshot will cause these assignments to be made every time the collection changes, including on deletes. If that's not your intention, fix by changing to get().

Getting a filtered array to save to a new array?

Making a calculator web app right now, and I want to save the the filtered array to a new array " operatorsNDInputList "
so that it saved the not duplicated operators to the array..
I need it to not run through the array till there has been atleast 2 inputs but then keep going even after there has been more than two inputs pushed the array?
Hope that makes sense maybe you'll be able to understand better if not after looking at the code:
'use strict';
const input = document.querySelector('#input'), // input/output button
numbers = document.querySelectorAll('.numbers div'), // number buttons
operators = document.querySelectorAll('.operators div'), // operator buttons
result = document.querySelector('#result'), // equal button
clear = document.querySelector('#clear'); // clear button
let numberInput = []
let operatorsInput = []
let operatorsNDInputList = []
document.querySelectorAll('.numbers div').forEach(buttonPress => {
buttonPress.addEventListener('click', (event) => {
numberInput.push(parseInt(event.target.textContent));
console.log(numberInput)
});
});
document.querySelectorAll('.operators div').forEach(buttonPress => {
buttonPress.addEventListener('click', (event) => {
operatorsInput.push(event.target.textContent);
console.log(operatorsInput)
});
});
operatorsInput.filter((item, index) => {
console.log(
item, index, operatorsInput.indexOf(item), operatorsInput.indexOf(item) === index,
);
return operatorsInput.indexOf(item) === index
});
I had got the duplicates of the operators to stop appearing, using the set method.
document.querySelectorAll('.operators div').forEach(buttonPress => {
buttonPress.addEventListener('click', (event) => {
operatorsInput.push(event.target.textContent);
let noDuplicates = [...new Set(operatorsInput)];
console.log(noDuplicates)
});
});

Using onClick to remove item from one array and place in another in React

I want to be able to click on a certain element and then remove it from the player1 array and place it into the playCard array. Currently this is attached to a button on the page.
choseCard = () => {
this.setState(({
playCard,
player1
}) => {
return {
playCard: [...playCard, ...player1.slice(0, 1)],
player1: [...player1.slice(1, player1.length)]
};
});
}
Currently this takes the first item from the player1 array and places it in the playCard array. I want to be able to select a certain element(card) from the player array instead of just taking the first element. I'm having a hard time thinking of the way to do this in react as I am still a beginner.
Is there a way to maybe move the selected card to the first element then use the above code?
try passing the index of element you are clicking on to the function, this might possibly work...
choseCard = (index) => {
this.setState(({playCard, player1}) =>
{
return
{
playCard: [...playCard, ...player1.slice(index, 1)],
player1: [...player1.slice(0, index),...player1.slice(index,player1.length)]
};
});
}
You can insert whatever logic you need right above the return statement, then return the results:
choseCard = () => {
this.setState(({playCard, player1}) => {
// change `index` to whichever index you want to remove
const index = 1;
const toInsert = player1[index];
const player1Copy = player1.slice();
player1Copy.splice(index, 1);
const playCardCopy = playCard.slice();
playCardCopy.push(toInsert);
return {
playCard: playCardCopy,
player1: player1Copy,
};
});
}
you could pass the card object in the choseCard function
choseCard(card) => {
const {playCard, player1} = this.state;
return this.setState({
playCard: playCard.concat(card),
player1: player1.filter(c => c.id !== card.id)
});
}
this is also under the assumption that each card has a unique identifier.

Draft.js. How to get all entities data from the ContentState

From official docs I know about 2 methods: get entity by its key and get last created entity. In my case, I also need a method to access all entities from current ContentState.
Is there any method that could perform this? If not, is there a one that can provide all entities keys?
const getEntities = (editorState, entityType = null) => {
const content = editorState.getCurrentContent();
const entities = [];
content.getBlocksAsArray().forEach((block) => {
let selectedEntity = null;
block.findEntityRanges(
(character) => {
if (character.getEntity() !== null) {
const entity = content.getEntity(character.getEntity());
if (!entityType || (entityType && entity.getType() === entityType)) {
selectedEntity = {
entityKey: character.getEntity(),
blockKey: block.getKey(),
entity: content.getEntity(character.getEntity()),
};
return true;
}
}
return false;
},
(start, end) => {
entities.push({...selectedEntity, start, end});
});
});
return entities;
};
How I get the all entities keys:
const contentState = editorState.getCurrentContent()
const entityKeys = Object.keys(convertToRaw(contentState).entityMap)
result:
[0, 1]
then you can call the getEntity(key) method to get the responding entity.
this is how convertToRaw(contentState) looks:
Bao, You will find it inside key called 'blocks'.
convertToRaw(contentState).blocks.map(el=>el.text)
It will give you an array of raw text.
Unfortunatelly your suggested way using convertToRaw doesnt work because it reindexes all keys to ["0", .., "n"], but the real keys differ when you act with the editor. New ones > n will be added and unused will be omitted.
const rawState = convertToRaw(contentState)
const { entityMap } = rawState;
This entityMap will have list of all entities. But this is an expensive conversion. Because, it will convert whole thing to raw. A better way is loop through blocks and check for entity.
You'll have to look at every character:
const { editorState } = this.state; // assumes you store `editorState` on `state`
const contentState = editorState.getCurrentContent();
let entities = [];
contentState.getBlockMap().forEach(block => { // could also use .map() instead
block.findEntityRanges(character => {
const charEntity = character.getEntity();
if (charEntity) { // could be `null`
const contentEntity = contentState.getEntity(charEntity);
entities.push(contentEntity);
}
});
});
Then you could access it via:
entities.forEach((entity, i) => {
if (entity.get('type') === 'ANNOTATION') {
const data = entity.get('data');
// do something
}
})

Categories

Resources