Show and Hide in a Foreach - javascript

I have a foreach loop going through my posts and each loop produces an html card with info inside from each post.
I want to show and hide items within the card on only that one card not every card that has been loaded. But I will need something to differentiate between the individual cards so the javascript doesn't hide all the info on all of the cards.
I wanted to know if anyone knows how I can achieve this with a javascript function to search only in elements within that element and not search the whole page.
My current show hide method
function show_hide_button_one() {
var a = document.getElementById("grid-item-1");
var b = document.getElementById("grid-item-2");
a.style.display = "block";
b.style.display = "none";
}
}
function show_hide_button_two() {
var x = document.getElementById("grid-item-1");
var y = document.getElementById("grid-item-2");
y.style.display = "block";
x.style.display = "none";
}
}
But with that method it shows and hides everything with the relative class
and not just for the card in use.
Its for lot's of posts. So I need a smarter route than my own method xD
pls help.

You have a couple of different options. You can use HTML data attributes to give each card unique identifiers beyond just ID or class name, or you can just make each card's ID's unique based on the post info. (Be careful not to give more than one card the same ID, as that will mess up your code!)
Here is a good artice on HTML data attributes:
https://www.sitepoint.com/how-why-use-html5-custom-data-attributes/
PS - Also, do this instead:
function show_hide_button(c1, c2) {
var a = document.getElementById(c1);
var b = document.getElementById(c2);
a.style.display = a.style.display === "block" ? "none" : "block";
b.style.display = b.style.display === "block" ? "none" : "block";
}
}

You must be having same id for all card. Have separate id for each card/button (whatever you are trying to hide). You will achieve what you desire.
Try doing this
//HTML
<div id="card1>
...
<button id="card1id1"></button>
<button id="card1id2"></button>
</div>
<div id="card2>
...
<button id="card2id1"></button>
<button id="card2id2"></button>
</div>
// JS
function show_hide_button_one(id1,id2) {
var a = document.getElementById(id1);
var b = document.getElementById(id2);
a.style.display = "block";
b.style.display = "none";
}
}
function show_hide_button_two(id1,id2) {
var x = document.getElementById(id1);
var y = document.getElementById(id2);
y.style.display = "block";
x.style.display = "none";
}
}
// calling
show_hide_button_one("card1id1", "card1id1")
show_hide_button_two("card1id1", "card1id1")

Related

Hide/Show fields with dynamic IDs (NodeJS, Mongoose, Express, Javascript)

I have a forEach loop which displays menus for different restaurants when the restaurant icon is clicked. The restaurant icons and the number of restaurants/menus is unknown and each is created with a dynamic ID, e.g. menu-0, menu-1, menu-2 etc.
When one restaurant icon is clicked, all the others should be hidden. Currently I have the below Javascript to show/hide the menus; while this is working, I'm working for a way to make it more dynamic/efficient, rather than a static list, given the number of menus is unknown.
let menu0 = document.getElementById('menu-0');
let menuIcon1 = document.getElementById('menu-icon-1');
let menu1 = document.getElementById('menu-1');
let menuIcon2 = document.getElementById('menu-icon-2');
let menu2 = document.getElementById('menu-2');
let menuIcon3 = document.getElementById('menu-icon-3');
let menu3 = document.getElementById('menu-3');
let menuIcon4 = document.getElementById('menu-icon-4');
let menu4 = document.getElementById('menu-4');
$('#menu-icon-0').on('click', function(e) {
if (menu0.style.display = 'none') {
menu0.style.display = 'block';
menuIcon0.style.border = '5px solid #2541B2';
menuIcon1.style.border = 'none';
menu1.style.display = 'none';
menuIcon2.style.border = 'none';
menu2.style.display = 'none';
menuIcon3.style.border = 'none';
menu3.style.display = 'none';
menuIcon4.style.border = 'none';
menu4.style.display = 'none';
}
})
$('#menu-icon-1').on('click', function(e) {
if (menu1.style.display = 'none') {
menu1.style.display = 'block';
menuIcon1.style.border = '5px solid #2541B2';
menuIcon0.style.border = 'none';
menu0.style.display = 'none';
menuIcon2.style.border = 'none';
menu2.style.display = 'none';
menuIcon3.style.border = 'none';
menu3.style.display = 'none';
menuIcon4.style.border = 'none';
menu4.style.display = 'none';
}
})```
from my experience you have to add custom class to your dynamic elements , then you can set the click on the class name for example, and inside the click you search for all elements that have this class, make for loop and compare the id of element with the clicked view id if not equals you should hide the boarder.
you are using jquery right? so all this can be boiled down to
$('#menu-icon-0').on('click', function(e) {
$('#menu-icon-0').toggle()
}

Switcher with getElementsByClassName("") not working

I am fairly new to Java but can't seem to fix this problem;
When using getElementsByClassName("") the toggle is not working I get the error "Cannot set property 'display' of undefined"
Also when testing this JS with getElementByID("") when double clicking on the English button the text disappeared completely. I want to keep one visible at all time (so either English/ German)
Is there a solution to fix this?
Thank you in advance :)
function showHideEnglish() {
var english = document.getElementsByClassName("text__english");
var german = document.getElementsByClassName("text__german");
german.style.display = "none";
if (english.style.display == "block") {
english.style.display = "none";
} else {
english.style.display = "block";
}
}
function showHideGerman() {
var english = document.getElementsByClassName("text__english");
var german = document.getElementsByClassName("text__german");
english.style.display = "none";
if (german.style.display == "block") {
german.style.display = "none";
} else {
german.style.display = "block";
}
}
<button onclick="return showHideEnglish();">English</button>
<button onclick="return showHideGerman();">German</button>
<div class="text__english" style="display:block;">This text is English</div>
<div class="text__german" style="display:none;">dieser Text ist auf Deutsch</div>
getElementsByClassName return a a collection of all elements with this class name
you need to access the elements inside the list
if you don't have other elements with the same class name this will work
var english = document.getElementsByClassName("text__english")[0];
var german = document.getElementsByClassName("text__german")[0];

Hide or show elements when user change buttons

I'm just going to create a function that allows me to hide some elements (filters on my website), while the other element ( All Categories) is selected. I'm using Sharetribe - marketplace CMS, here's mine https://rentim.sharetribe.com/
Here's piece of code I wrote to make it happen, but it's not working
document.querySelectorAll('a.home-categories-main:first-child.selected'),
function hideFilters() {
document.getElementById('filters').style.display = 'none';
};
Here is a working example on JSFiddle.
This is a simple example to what you are trying to do using the most basic HTML and JS combination.
Nothing fancy, but it works.
HTML:
<div id="first" onclick="hideFilters();">All</div>
<div id="filters">
<div>Price</div>
<div>Model</div>
<div>Date</div>
<div>Color</div>
</div>
Javascript:
var a = true;
function hideFilters(){
let x = document.getElementById("filters");
if(a){
x.style.display = "none";
}else{
x.style.display = "block";
}
a = !a;
}
Here is a working example on JSFiddle.
In Rentim you should add custom scripts with onDocumentReady function. It's executed after HTML is parsed and all elements rendered.
onDocumentReady(function() {
var filters = document.querySelector('#filters');
var allCategories = document.querySelector('.home-categories-main:first-child.selected');
filters.style.display = allCategories ? 'block' : 'none';
});

javascript using a loop to change the display of every element that has a specific class

Yesterday I asked a question about improving efficiency in my code. Today I have another question in the same spirit of trying to write less lines of code to accomplish repetitive tasks.
I have the following code:
function myIntroductionText() {
introPos.style.display = 'block';
posOne.style.display = 'none';
posTwo.style.display = 'none';
posThree.style.display = 'none';
posFour.style.display = 'none';
posFive.style.display = 'none';
posSix.style.display = 'none';
posSeven.style.display = 'none';
posEight.style.display = 'none';
posNine.style.display = 'none';
posTen.style.display = 'none';
posEleven.style.display = 'none';
backButton.style.visibility = 'hidden';
}
function myPositionOne() {
introPos.style.display = 'none';
posOne.style.display = 'block';
posTwo.style.display = 'none';
posThree.style.display = 'none';
posFour.style.display = 'none';
posFive.style.display = 'none';
posSix.style.display = 'none';
posSeven.style.display = 'none';
posEight.style.display = 'none';
posNine.style.display = 'none';
posTen.style.display = 'none';
posEleven.style.display = 'none';
backButton.style.visibility = 'visible';
}
function myPositionTwo() {
introPos.style.display = 'none';
posOne.style.display = 'none';
posTwo.style.display = 'block';
posThree.style.display = 'none';
posFour.style.display = 'none';
posFive.style.display = 'none';
posSix.style.display = 'none';
posSeven.style.display = 'none';
posEight.style.display = 'none';
posNine.style.display = 'none';
posTen.style.display = 'none';
posEleven.style.display = 'none';
}
The HTML looks something like this:
<p class="textContent" id="introductionText">Introduction Text Goes Here</p>
<p class="textContent" id="position1">content1</p>
<p class="textContent" id="position2">content2</p>
<p class="textContent" id="position3">content3</p>
Each position (i.e. introPos, posOne, posTwo) also has a corresponding function that looks essentially the same as the function above, except it changes the display based on which position it is in.
I'm thinking that I could use a loop and/or an if/else statement to make this task more efficient. I tried by using getElementsByClassName('textContent'), which (I think) produced an array containing all of the elements with that class. According to the console.log is contains [p#introductionText.textContent, p#position1.textContent, so on and so on...]. So, I wrote the following code to try to loop through it:
var blanks = document.getElementsByClassName("textContent") // this creates the array that I mentioned
for (item in blanks) {
if (blanks[0] === introductionText.textContent) {
blanks[0].style.display = 'block';
} else {
blanks[item].style.display = 'block';
}
}
I tried using p#introductionText.textContent but that returned an error. I'm very new to JavaScript so I fully recognize that I could be doing something very silly here, but any help would be appreciated.
EDIT:
The error message says Uncaught SyntaxError: Unexpected tocken ILLEGAL
I should also add that my goal is to have only one position be visible at each time. I have a "Back" and "Next" button that allows users to go from posOne to posTwo, to posThree, and so on. So, in addition to making posTwo visible, I also need to make posOne and/or posThree not visible.
Thanks!
The first thing is moving all those Javascript style expressions to CSS:
#introPos,
#posOne,
#posTwo,
#posThree,
#posFour,
#posFive,
#posSix,
#posSeven,
#posEight,
#posNine,
#posTen,
#posEleven {
display: none;
}
Or even shorter
#introductionText>.textContent {
display: none;
}
This would enable you to shorten each function considerably:
function myPositionOne() {
posOne.style.display = 'block';
backButton.style.visibility = 'visible';
}
Instead of setting each style via JS again and again, you'd simply set those that change.
The next step would be to rewrite all those functions into one that accepts a parameter which element you are targeting:
function myPosition(pos) {
var parent = document.getElementById("text-container");
var children = parent.getElementsByClassName("textContent");
var element;
// first hide all <p class="textContent"> children
for (var i = 0; i < children.length; i++) {
children[i].style.display = 'none';
if (i == pos) {
element = children[i];
}
}
// then show the right one
if (element) {
element.style.display = 'block';
}
// show or hide the back button depending on which child we are dealing with
if (pos > 0) {
document.getElementById("backButton").style.visibility = 'visible';
} else {
document.getElementById("backButton").style.visibility = 'hidden';
}
if (pos >= children.length-1) {
document.getElementById("nextButton").style.visibility = 'hidden';
} else {
document.getElementById("nextButton").style.visibility = 'visible';
}
}
This sets only the child number #pos visible and adjusts the visibility of the back button (assuming the back button has the ID "backButton").
Maybe this:
All paragraphs also have the class "textContent". Make this display none and display the correct paragraph via given paragraph-id:
function myFunction(classDisplay) {
var elems = document.getElementsByClassName('textContent');
for (var i=0;i<elems.length;i+=1){
elems[i].style.display = 'none';
}
document.getElementById(classDisplay).style.display = "block";
}
The following will hide all but position 2:
myFunction("position2");
I don't know about the back-button, this is always be visible?
EDIT: I've tested this and corrected the code.
If you use JQuery, you can also use the following instead of the for loop:
$('.textContent').css('display'​​​​​​​​​​​​​​​​​​​​​​​​​​​,'none');​​​​​​
In newer versions of JavaScript you can use:
Array.from(document.getElementsByClassName('myclass')).forEach((item) => {
item.style.backgroundColor = "blue";
})

How to code my javascript in order for toggle to work properly?

I have javascript code to toggle hide and show information and works for one showMoreText section of text, but want 16 different toggle options for all the different links. Included is the image that works for the "Montana's Glacier" underneath Why is it Important? It does toggle, but I created another javascript page (toggle2.js) specifically for the "Ice now covers..." link, but it will not appear.
Code for first toggle option in toggle.js
window.onload = function(){
document.getElementById('toggle').onclick = showMore;
}
function showMore(){
var div = document.getElementById('showMoreText');
var display = div.style.display;
display == "none" ? div.style.display = "block" : div.style.display = "none";
}
Code for second toggle option in toggle2.js
window.onload = function(){
document.getElementById('toggle2').onclick = showMore;
}
function showMore(){
var div = document.getElementById('showMoreText2');
var display = div.style.display;
display == "none" ? div.style.display = "block" : div.style.display = "none";
}
Code within HTML for toggle1
<div id="showMoreText" style="display: none"> (missing paranthesis)
Code within HTML for toggle2
<div id="showMoreText" style="display: none"> (missing paranthesis)
What is wrong? I want to be able to toggle to many different toggles (1-16) but when I click on toggle1, and want to click on toggle 2, it does not change. what variable is barring me from it work properly?
Thank you!
Further Optimised based on Aleks G answer:
Your script:
window.onload = function(){
for(var i=0; i<3; i++){ //here is set to 3
document.getElementById('toggle'+i).onclick = function(i){
return function(){
showMore('showMoreText'+i);
}
}(i);
}
}
function showMore(id){
var div = document.getElementById(id),
display = div.style.display;
display == "none" ? div.style.display = "block" : div.style.display = "none";
}
HTML:
<div id="toggle1" class="toggle"></div>
<div id="toggle2" class="toggle"></div>
<div id="toggle3" class="toggle"></div>
CSS:
div.toggle{
display: none;
}
Actually, you don't even need the id in div. You can just loop through the class toggle and find all the divs.
Why do you need to have all toggles separately? Why not just do this?
window.onload = function(){
document.getElementById('toggle').onclick = showMore1;
document.getElementById('toggle2').onclick = showMore2;
document.getElementById('toggle3').onclick = showMore3;
...
}
function showMore1() { showMore('showMoreText'); }
function showMore2() { showMore('showMoreText2'); }
function showMore3() { showMore('showMoreText3'); }
...
function showMore(id){
var div = document.getElementById(id);
var display = div.style.display;
display == "none" ? div.style.display = "block" : div.style.display = "none";
}
This is quite crude, feel free to optimise further.
Not a complete answer, but just to go with the above, the window.onload function can be simplified into a single object, and the code recylcled.
window.onload = function() {
var tList={'toggle1': 'showMore1','toggle2': 'showMore2','toggle3': 'showMore3'};
for(var i in tList){document.getElementById(i).onclick = tList[i]};
}

Categories

Resources