Multiple conditions for querySelector() - JavaScript - javascript

I'm not sure if is this what i need but i think its neccesery. Propably i need add another condition to this line
const div = document.querySelector(`#result_${i}`);
I have simple .js file with array of object. Currently every object has question, answer. I would like to expand it by "text" where i would tell some details about results etc.
//For Text
const text = document.createElement("div");
text.id = "text_" + i;
text.style.display = "none";
text.classList.add("pokus");
text.innerHTML = ex.text;
card.appendChild(text);
Logic is same as for answer. I can see it in the DOM but it's it's not showing for user. I think the reason is missing condition in querySelector? If yes. How can i add another? I tried (`#result_${i}, #text_$(i)`) or (`#result_${i}`, `#text_${i}`);
Whole code.
import("./Objects/" + selectedPage + ".js")
.then((array) => {
const { examples } = array;
console.log(array);
function toggle(i) {
const div = document.querySelector(`#result_${i}`);
if (div.style.display !== "none") {
div.style.display = "none";
} else {
div.style.display = "block";
}
}
const container = document.querySelector("#examples-container");
examples.forEach((ex, i) => {
const card = document.createElement("div");
card.classList.add("card");
const example = document.createElement("div");
example.classList.add("example");
example.innerHTML = ex.question;
card.appendChild(example);
//For Button
const button = document.createElement("button");
button.classList.add("toggle");
button.innerHTML = "výsledek";
button.addEventListener("click", () => toggle(i));
card.appendChild(button);
//For answer
const result = document.createElement("div");
result.id = "result_" + i;
result.style.display = "none";
result.classList.add("result");
result.innerHTML = ex.answer;
card.appendChild(result);
//For Text
const text = document.createElement("div");
text.id = "text_" + i;
text.style.display = "none";
text.classList.add("pokus");
text.innerHTML = ex.text;
card.appendChild(text);
// Add the card to the container
container.appendChild(card);
});
})
.catch((err) => {
console.log(err);
});

Im not 100% sure I understand your question, but right now you're using QuerySelector and it will only return the first element.
If you want to select multiple elements use QuerySelectorAll / getElementByClassName and then loop over the list they return.

Use querySelectorAll
As you want to target more than 1 node (here result, text) you need to use querySelectorAll instead of querySelector
function toggle(i) {
const divs = document.querySelectorAll(`#result_${i}`,`#text_${i}`);
for (let div of divs) {
if (div.style.display !== "none") {
div.style.display = "none";
} else {
div.style.display = "block";
}
}
}

Related

A function to remove a div element that contains specific text in Javascript?

I've written a simple code that takes text from the input field, stores it as a string in an array and creates a div with that same text every time the "add" button is pressed.
Then there's a "remove" button, that removes the item from array if the input matches the item in the array.
I need a function to remove the previously created div with the same text inside as the current input.
E.g. if I type "book1" press "add" - array gets 'book1' as a first item and a div "book1" is created, "book2", "book3" and so on. If I type 'book2' and press remove, it gets removed from the array and a respective div should be removed.
That last function I just can't figure out.
let addBtn = document.getElementById("add-btn");
let removeBtn = document.getElementById("rmv-btn");
let bookArray = [];
addBtn.addEventListener("click", addBook);
removeBtn.addEventListener("click", removeBook);
let innerDiv = document.body.newDiv.innerHTML
function addBook() {
newBook = document.getElementById("input").value;
if (newBook != '') {
bookArray.push(newBook);
addElement();
clear();
console.log(bookArray);
} else {
clear();
console.log(bookArray);
}
}
function removeBook() {
inputBook = document.getElementById("input").value;
for (i = 0; i < bookArray.length; i++) {
if (inputBook.toString() === bookArray[i].toString()) {
bookArray.splice([i], 1);
console.log(bookArray);
removeElement()
return;
} else {
clear();
}
}
console.log(bookArray);
}
function clear() {
document.getElementById("input").value = "";
}
function addElement() {
let newDiv = document.createElement("div");
newDiv.innerHTML = newBook;
my_div = document.getElementById("mydiv");
document.body.appendChild(newDiv, my_div);
}
function removeElement() {
alert("this bit needs working out");//???
}
<input type="text" id="input" />
<button id="add-btn">Add</button>
<button id="rmv-btn">Remove</button>
<div id="mydiv"></div>
</div>
You need to change how you are adding the div because it adding it outside and not as a child of my_div
let addBtn = document.getElementById("add-btn");
let removeBtn = document.getElementById("rmv-btn");
let bookArray = [];
addBtn.addEventListener("click", addBook);
removeBtn.addEventListener("click", removeBook);
function addBook() {
newBook = document.getElementById("input").value;
if (newBook != '') {
bookArray.push(newBook);
addElement();
clear();
console.log(bookArray);
} else {
clear();
console.log(bookArray);
}
}
function removeBook() {
inputBook = document.getElementById("input").value;
for (i = 0; i < bookArray.length; i++) {
if (inputBook.toString() === bookArray[i].toString()) {
bookArray.splice([i], 1);
console.log(bookArray);
removeElement(i);
return;
} else {
clear();
}
}
console.log(bookArray);
}
function clear() {
document.getElementById("input").value = "";
}
function addElement() {
let newDiv = document.createElement("div");
// count number of children in mydiv
let count = document.getElementById("mydiv").childElementCount;
// add an id
newDiv.id = 'mydiv-' + count;
newDiv.innerHTML = newBook;
my_div = document.getElementById("mydiv");
my_div.appendChild(newDiv, my_div);
}
function removeElement(el) {
// remove html element from dom
let my_div = document.getElementById("mydiv");
my_div.removeChild(my_div.childNodes[el]);
}
A workaround to remove book by the input value by user:
Modify the addElement function to:
function addElement() {
let newDiv = document.createElement("div");
newDiv.innerHTML = newBook;
newDiv.setAttribute('data-book-name', newBook); //new added line | setting data attribute
my_div = document.getElementById("mydiv");
document.body.appendChild(newDiv, my_div);
}
removeElement will be:
function removeElement() {
document.querySelector('[data-book-name="'+ newBook +'"]')?.remove();
}
But this will remove first book in the DOM. If you want to remove all books with same name use:
function removeElement() {
var books = document.querySelectorAll('[data-book-name="'+ newBook +'"]');
if(books.length == 0) return;
books.forEach(x => x.remove())
}

Can't hide the DIV

any idea why the div doesn't toggle?
I tried also to recall with html, i think i'm missing something, but i don't know what, to me looks ok, but for sure something is missing,
albums.forEach((album) => {
html += `<div class="user"><h2>User ${album.id} Album</h2>`;
let albumPhotos = photos.filter(p => p.albumId == album.id);
html += `<div>`
albumPhotos.forEach(photo => {
html += `<div id="myDIV">
<img src="${photo.thumbnailUrl}">
</div>
`;
});
html += '</div>';
});
// i call back the container set in html
let container = document.querySelector(".container");
container.innerHTML = html;
let container2 = document.querySelector(".button");
container.innerHTML = html;
}
// function recall
renderUsers();
function myFunction() {
var x = document.getElementById("myDIV");
if (x.style.display === "none") {
x.style.display = "block";
} else {
x.style.display = "none";
}
}
</script>
You are adding <div id="myDIV"> for each photo, but you're supposed to have unique ids on the page.
You can't have divs with the same id - they should be different. In your case you cloud use class and not id.
Is this the kind of behaviour you're looking for?
<div class="container"></div>
<button class="button" onclick="toggleImages()">Toggles Images</button>
<script>
let html = '';
let albumPhotos = [1,2,3,4,5,6,7];
html += `<div>`;
albumPhotos.forEach(photo => {
html += `<div class="myDIV"><p>${photo}</p></div>`;
});
html += '</div>';
let container = document.querySelector(".container");
container.innerHTML = html;
let container2 = document.querySelector(".button");
container.innerHTML = html;
function toggleImages() {
var x = document.getElementsByClassName("myDIV");
for (let elem of x) {
if (elem.style.display === "none") {
elem.style.display = "block";
} else {
elem.style.display = "none";
}
}
}

Loop through <li> and display list containing input value

I have a list of items like a todo list and i have a search input where i want users to search through the list'
I am using the keyup event and if input matches i am trying to use css to set the matched li to display:'' while the list items that do not match i want to set display:none.
so far i am able to console.log my results but cant effect changes to my li list as the css to set display none doesn't work.
here is my code below.
const Ul = document.querySelector('.clipBoard');
const search = document.querySelector('.search');
array.forEach((item) => {
let button = document.createElement('button');
button.className =
'list-group-item buttonLi';
button.innerText += item;
Ul.appendChild(button);
//Search function
search.addEventListener('keyup', () => {
let filterValue = search.value;
const li = Ul.querySelectorAll('.buttonLi');
for (let i = 0; i < li.length; i++) {
let List = li[i];
if (List.innerHTML.indexOf(filterValue) > -1) {
console.log(li[i].innerHTML);
li[i].style.display = '';
} else {
li[i].style.display = 'none';
}
}
});
I would suggest you to assign an id to each element using the index at that level:
array.forEach((item, INDEX) => {
let button = document.createElement('button');
var id = 'el-'+INDEX
button.setAttribute("id", id);
button.setAttribute("class", "list-group-item buttonLi");
button.innerText += item;
});
Then on your search function use that id to hide the elements
search.addEventListener('keyup', () => {
let filterValue = search.value;
const li = Ul.querySelectorAll('.buttonLi');
for (let i = 0; i < li.length; i++) {
let List = li[i];
if (List.innerHTML.indexOf(filterValue) > -1) {
console.log(li[i].innerHTML);
// something like that
var idToShow = '#el-'+i;
document.querySelector(idToShow).style.display = 'block';
} else {
// something like that
var idToHide = '#el-'+i;
document.querySelector(idToHide).style.display = 'none';
}
}
});
I did not test this code, just trying to point you to an eventual solution!
You could also do the filtering on your array then for each search you re-render your list!

I am working on TODO, I want the bin image and list style image to have space in between but when i apply flex property on "list" the image dissapear

I want the List-Style-Image to be Apppear while using "flex" and have space between "bin" image and List-Style-Image . I dont know why every time i apply the flex-property on "Li" the image dissapear's
let input = document.querySelector("#textFeild");
let button = document.querySelector("#button");
let toDoContainer = document.querySelector("#toDoContainer");
let ul = toDoContainer.querySelector("ul");
// Adding Event on Button
button.addEventListener("click", function(){
let li = document.createElement('li');
li.style.listStyleImage = "url('assets/icons/checkbox.png')";
li.style.display = "list-item";
li.innerText = input.value;
li.style.fontSize = "30px";
li.style.borderBottom = "1px solid #f2f1f1";
li.style.padding = "20px";
li.style.display = "flex"; //problem is here
li.style.justifyContent = "space-between";
ul.appendChild(li);
let bin = document.createElement("IMG");
bin.setAttribute("src", "assets/icons/bin.png");
bin.setAttribute("width", "30");
bin.style.marginLeft = "auto";
li.appendChild(bin);
input.value = ""; //It will Clear the Feild for next Value.
//We write Event-listner on Paragrahs (Nested) Here Because of "let" Block-Scope.
li.addEventListener("click", function(){
li.style.textDecoration = "line-through";
li.style.listStyleImage = "url('assets/icons/checkmark.png')";
})
bin.addEventListener("click", function(){
ul.removeChild(li);
})
})
You are setting li.style.display = "list-item"; and then rewriting it to flex. Property listStyleImage is for elements with display: list-item

Displaying div based on dropdown value

I have 3 divs each with a distinct id. Based off the value of a dropdown I have, I want to show one of the divs. I created my function and call it, but for some reason no change occurs. The new value of the dropdown is never recorded, when I use console.log. I am unsure what is causing the problem and would appreciate any help.
HTML
<div class="ins-left" id="fifteen">
<p>$15</p>
</div>
<div class="ins-left" id="thirty">
<p>$30</p>
</div>
<div class="ins-left" id="fourtyfive">
<p>$45</p>
</div>
CSS
#fifteen {
display: none;
}
#thirty {
display: none;
}
#fourtyfive {
display: none;
}
JS
var length = document.getElementById('length');
var chosenLength = length.options[length.selectedIndex].value;
var start = document.getElementById('start').innerHTML.split('.').join('').toLocaleLowerCase();
var end = document.getElementById('end').innerHTML.split('.').join('').toLocaleLowerCase();
var time = document.getElementById('time');
time.disabled = true;
function disabled() {
if (chosenLength.value != "") {
time.disabled = false;
}
}
var slotTimes = [];
document.getElementById("length").onchange = function (evt) {
var timeDistance = evt.target.value;
var startMoment = moment(start, "h:mm a");
var endMoment = moment(end, "h:mm a");
slotTimes = [];
while (startMoment.isSameOrBefore(endMoment)) {
slotTimes.push(startMoment.format("h:mm a"));
startMoment = startMoment.add(timeDistance, 'minutes');
}
addDropdown();
price();
};
function price(){
if (chosenLength.value === "") {
document.getElementById('fifteen').style.display = "none";
document.getElementById('thirty').style.display = "none";
document.getElementById('fourtyfive').style.display = "none";
}
if (chosenLength.value === "30") {
document.getElementById('fifteen').style.display = "block";
document.getElementById('thirty').style.display = "none";
document.getElementById('fourtyfive').style.display = "none";
}
if (chosenLength.value === "60") {
document.getElementById('fifteen').style.display = "none";
document.getElementById('thirty').style.display = "block";
document.getElementById('fourtyfive').style.display = "none";
}
if (chosenLength.value === "90") {
document.getElementById('fifteen').style.display = "none";
document.getElementById('thirty').style.display = "none";
document.getElementById('fourtyfive').style.display = "block";
}
}
function addDropdown() {
var doc = '',
times = slotTimes,
i;
for (i = 0; i < times.length; i++) {
doc += "<option value='" + times[i] + "'>" + times[i] + "</option>";
}
document.getElementById('time').innerHTML = doc;
disabled();
}
I made a simple working example for you here, so you can adjust your code based on this:
https://codepen.io/brunomont/pen/WmExvV
I had to remove a couple of broken references since your HTML didn't include everything (like the time elements). Also, make sure you have all the dependencies loading (I noticed you are using moment.js).
The changes I made were:
Adding a document.addEventListener("DOMContentLoaded", function() to make sure your HTML was loaded, before you tyr to run the JavaScript.
Change the way you bind your onChange function to be document.getElementById('length').addEventListener('change', function (evt)
Basically, the addEventListener is more flexible than onChange. You can read more about this change here:
addEventListener vs onclick
Hope it helps :)

Categories

Resources