Hide or show elements when user change buttons - javascript

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';
});

Related

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];

Javascript code doesn't fire until the 2nd click for an html button?

I'm learning javascript, and this simple piece of code just won't work the way I need it to.
All I need is to display the main tag at the click of a button. HOWEVER, it doesn't want to display until the SECOND click.
So the first click doesn't display the main. The second click does.
I've tried moving my coding around the html document (before/after body closing tag, etc).
I've looked through stack overflow, and similar questions don't really help my case. Or at least I don't understand how they can help me as a beginner.
var aboutShow = document.getElementById("aboutLink");
aboutShow.addEventListener("click", displayMain);
function displayMain(){
var mainSection = document.getElementsByTagName("main")[0];
if (mainSection.style.display === "none"){
mainSection.style.display = "grid";
}
else{
mainSection.style.display = "none";
}
}
main{display:none;}
<main> ... </main>
<button type="button" id="aboutLink">About</button>
There has to be something I'm missing that prevents that 1st click from firing the code. I mean, it seems simple enough???
if (mainSection.style.display === "none") is looking for an inline style tag, so instead of setting display:none; in your CSS, just set it inline on the element:
var aboutShow = document.getElementById("aboutLink");
aboutShow.addEventListener("click", displayMain);
function displayMain(){
var mainSection = document.getElementsByTagName("main")[0];
if (mainSection.style.display === "none"){
mainSection.style.display = "grid";
}
else{
mainSection.style.display = "none";
}
}
<main style="display:none;"> ... </main>
<button type="button" id="aboutLink">About</button>
As has been answered, mainSection.style.display is empty. Another option is to get the computed style of the element:
var aboutShow = document.getElementById("aboutLink");
aboutShow.addEventListener("click", displayMain);
function displayMain() {
var mainSection = document.getElementsByTagName("main")[0];
if (window.getComputedStyle(mainSection).getPropertyValue('display') === "none") {
mainSection.style.display = "grid";
} else {
mainSection.style.display = "none";
}
}
main {
display: none;
}
<main> ... </main>
<button type="button" id="aboutLink">About</button>
var aboutShow = document.getElementById("aboutLink");
aboutShow.addEventListener("click", displayMain);
function displayMain(){
var mainSection = document.getElementsByTagName("main")[0];
if (mainSection.style.display || "none" === "none"){
mainSection.style.display = "grid";
}
else{
mainSection.style.display = "none";
}
}
main{display:none;}
<main>text</main>
<button type="button" id="aboutLink">About</button>
Initially mainSection.style.display is empty, so it falls on the else part of the if statement and changes the property to none.
On the second click, the property now has the value of none, that's why it works on the second click.
The HTMLElement.style property is used to get as well as set the inline style of an element.

Show and Hide in a Foreach

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")

Why won't my JavaScript work!? It's selecting the ID but won't apply display changes

Before I get in to this, I know I should learn jQuery but I haven't got to that yet, I want to learn raw JavaScript first! Well, mostly. Can someone help me without the use of jQuery please just for understanding, thank you!:
Hi, I'm new to JavaScript, not long started learning it as you can see by the first code (which works so I'm leaving it) for the navigation.
However, my problem comes on the 2nd piece of code I'm trying something from a different angle after watching videos on event listeners etc and everything I have written makes sense, to me, I'm going through it step by step, it's selecting all the right stuff, but it's still not showing the desired result!!
When you click CSS i want it to show the div with id "cs", and same for the HTML and JavaScript ones.
I really don't know JavaScript enough to solve this myself, I can not think of anything AT ALL to help with the problem!
Somebody save me, please, my mind is going crazy and I want to go to bed!
Here is the code, and here is the JS fiddle: https://jsfiddle.net/pmj26o9p/2/
var htm = document.getElementById('htm');
var css = document.getElementById('css');
var js = document.getElementById('js');
htm.addEventListener("click", contentShow);
css.addEventListener("click", contentShow);
js.addEventListener("click", contentShow);
function contentShow() {
var whichOne = this.attributes["data-id"].value;
var switcheroo = document.getElementById(whichOne);
switcheroo.onclick = function() {
if (switcheroo.style.display === "none") {
switcheroo.style.display = "";
} else {
switcheroo.style.display = "none";
}
}
EDIT: On reading through the code again I don't think it will achieve what I want even if it works. This will let me show and hide whichever I'm clicking right?
I want to show the clicked one but then hide / apply display:none to all others that aren't clicked.
My example below will show the chosen block and hide the others, as per your EDIT comment.
var htm = document.getElementById('htm');
var css = document.getElementById('css');
var js = document.getElementById('js');
function contentShow(el) {
var whichOne = el.attributes["data-id"].value;
var switcheroo = document.getElementById(whichOne);
// show selected block, hide the others
switch (switcheroo) {
case htm:
htm.style.display = "block";
css.style.display = "none";
js.style.display = "none";
break;
case js:
htm.style.display = "none";
css.style.display = "none";
js.style.display = "block";
break;
case css:
htm.style.display = "none";
css.style.display = "block";
js.style.display = "none";
break;
}
}
<span data-id="htm" onClick="contentShow(this)" style="margin-right:10px;color:red; cursor:pointer">Click to show the HTML Block</span>
<span data-id="css" onClick="contentShow(this)" style="margin-right:10px;color:green; cursor:pointer">Click to show the CSS Block</span>
<span data-id="js" onClick="contentShow(this)" style="margin-right:10px;color:blue; cursor:pointer">Click to show the JS Block</span>
<br/>
<br/>
<div id="htm">Some HTML info here</div>
<div id="css" style="display:none">Some CSS info here</div>
<div id="js" style="display:none">Some JavaScript info here</div>
you are binding a second event handler to the switcheroo element, but the click event is not triggered so nothing happens.
If you want to make a toggle function on the switcheroo variable, you should do this instead:
function contentShow() {
var whichOne = this.attributes["data-id"].value;
var switcheroo = document.getElementById(whichOne);
return toggleDisplay(switcheroo);
}
function toggleDisplay(elem) {
if (elem.style.display === "none") {
elem.style.display = "";
} else {
elem.style.display = "none";
}
}
Ignoring your other bad practices, change
var htm = document.getElementById('htm');
var css = document.getElementById('css');
var js = document.getElementById('js');
htm.addEventListener("click", contentShow);
css.addEventListener("click", contentShow);
js.addEventListener("click", contentShow);
function contentShow() {
var whichOne = this.attributes["data-id"].value;
var switcheroo = document.getElementById(whichOne);
switcheroo.onclick = function() {
if (switcheroo.style.display === "none") {
switcheroo.style.display = "";
} else {
switcheroo.style.display = "none";
}
}
to something more like:
var doc = document;
function E(id){
return doc.getElementById(id); // you guessed it - same as document.getElementById, without typing it every time
}
var htm = E('htm'), css = E('css'), js = E('js');
contentShow = (function(){ // self-executing scopes off var showing - variable style assignment requires function definition before execution
var showing = false;
return function(){ // returns unexecuted function
var ht = E('ht').style, cs = E('cs').style, jsc = E('jsc').style;
if(showing){
ht.display = cs.display = jsc.display = 'none'; showing = false;
}
else{
ht.display = cs.display = jsc.display = 'block'; showing = true;
}
}
})();
htm.addEventListener('click', contentShow);
css.addEventListener('click', contentShow);
js.addEventListener('click', contentShow);
See updated JSFiddle here.
If there are no other click Events on those Elements, you could even change
htm.addEventListener('click', contentShow);
css.addEventListener('click', contentShow);
js.addEventListener('click', contentShow);
to
htm.onclick = css.onclick = js.onclick = contentShow;
JSFiddle here
but keep in mind this technique overwrites previous Events of the same type.
Here is a variation of #K Scandrett answer which add some scalability/flexibility
var navElements = document.getElementsByClassName("nav");
//Add Event Listeners
for(var i = 0; i < navElements.length; i ++)
{
navElements[i].addEventListener('click', contentShow, false);
}
function contentShow(el) {
var whichOne = el.target.attributes["data-id"].value;
var target = document.getElementById(whichOne);
for(var i = 0; i < navElements.length; i ++)
{
var content = document.getElementById(navElements[i].attributes["data-id"].value)
content.style.display = content === target ? "block" : "none";
}
}
<span data-id="htm" style="margin-right:10px;color:red; cursor:pointer" class="nav">Click to show the HTML Block</span>
<span data-id="css" style="margin-right:10px;color:green; cursor:pointer" class="nav">Click to show the CSS Block</span>
<span data-id="js" style="margin-right:10px;color:blue; cursor:pointer" class="nav">Click to show the JS Block</span>
<br/>
<br/>
<div id="htm">Some HTML info here</div>
<div id="css" style="display:none">Some CSS info here</div>
<div id="js" style="display:none">Some JavaScript info here</div>
I know you're looking for a javascript solution here.and kudos to you for wanting to understand javascript before getting into jquery, but here is an out of the box solution for you.... pure HTML and CSS
.info {display:none;}
.info:target{display:block;}
Click to show the HTML Block
Click to show the CSS Block
Click to show the JS Block
<br/>
<br/>
<div id="htm" class="info">Some HTML info here</div>
<div id="css" class="info">Some CSS info here</div>
<div id="js" class="info">Some JavaScript info here</div>
What I've done here is, leverage internal page id links and the :target selector. In my mind, this is more semantic and can also still be extended by scripting while still maintaining semantics. This option also gives your uses the option of bookmarking selections etc.
CSS OPTION 2
This option achieves the initial display. It is not as clean and uses absolute positioning and z-indexes. Alos note that is uses a background color to conceal the initial option.
.info {position:relative;}
.info > div {
position:absolute;
top:0;
left:0;
background-color:#FFF;
z-index:10;
display: none;
}
#htm
{
display:block;
z-index:1;
}
.info > div:target {
display: block;
}
Click to show the HTML Block
Click to show the CSS Block
Click to show the JS Block
<br/>
<br/>
<div class="info">
<div id="htm">Some HTML info here</div>
<div id="css">Some CSS info here</div>
<div id="js">Some JavaScript info here</div>
</div>
On a side note you should consider adding/removing css classes using javascript instead of the display property directly. This will enable the use of CSS transitions.

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