How would I efficiently toggle different divs using an h tag? - html

I am attempting to show a certain div when the relative li is selected. If any other divs are showing, I need to hide that one and only display the new one. There 1000% is a way more efficient way to do this then creating many useStates.
import {useState} from 'react'
import './dope.css'
export const PageContent = () => {
const [one, setOne] = useState('false')
const [two, setTwo] = useState('false')
function toggle1(){
set1(!1)
}
function toggle2(){
set2(!2)
}
return (
<section>
<div className='middle_wrapper'>
<div className='left_menu_wrapper'>
<nav className='nav_black'>
<li><a href='#!' onClick={toggle1}>1</a></li>
<li><a href='#!' onClick={toggle2}>2</a></li>
<li><a href='#!'>3</a></li>
<li><a href='#!'>4</a></li>
<li><a href='#!'>5</a></li>
<li><a href='#!'>6</a></li>
<li><a href='#!'>7</a></li>
<li><a href='#!'>8</a></li>
<li><a href='#!'>9</a></li>
<li className='no_border'><a href='/'>10</a></li>
</nav>
</div>
<div className='right_content'>
<section className='full_page'>
<div id='new_res' className={one? 'inactive' : 'active'}>
<h1>This is a 1 test</h1>
</div>
<div id='all_res' className={two? 'inactive' : 'active'}>
<h1>This is a 2 test</h1>
</div>
</section>
</div>
</div>
</section>
)
}
---- From dope.css ----
.active {
display: block;
}
.inactive {
display: none;
}
--------
https://gyazo.com/1838ccf473832a00f341f4366b97b670
Like above, I would like to make this more efficient, it's probably something very simple that I am overlooking because I am tired and need sleep. I think I could simply just toggle the div's using href='#new_res' but how would I keep it hidden if it's not in use?
Any help would be appreciated, I know this is something simple and I by time someone answers, I may have found the solution. If not, thank you for helping!

If possible, it would be more efficient to simply use a checkbox.
However, if you have to use React state for flexibility, you could make a state with an array instead:
const [checkedArray, setCheckedArray] = useState([])
Whenever there is a new div to check toggle state, push a false into the array, when it is clicked, turn it to be true:
// Example
// Adding new state
setCheckedArray((current)=>[...current,false])
// Mutating 3rd item's state
setCheckedArray((current)=>{
const newArray = [...current];
newArray[3] = true;
return newArray
})
// Getting the info of the 3rd item of the array
const stateOfThirdItem = checkedArray[3]

Create a state to store all the components and their visibility flag. This will allow you to loop through them to dynamically render the anchors (and their onClick event) and also show them in the DOM.
https://codesandbox.io/s/so-71716290-bdsp9w?file=/src/PageContent.js

Related

JQuery populate div with link content but also need to move (like anchor link) to area where div located

I have unordered list of links. Using JQuery, when clicked, the link's contents (a div with image and text) are loaded into the section specified. This all works beautifully. But I'm wondering how to also get the onclick function to move the view to the div's location on the page similarly to how anchor tag works. Here is the site where you can see the div being populated, but not moving down to view it. https://www.thecompassconcerts.com/artists.php
My JQuery knowledge is not awesome (I'm being generous).
I followed Osama's suggestion to add event listener and I got almost correct results. Upon first click...contents are loaded but do not move. But on every successive click, it functions perfectly: Contents loaded and move to div (like an anchor link) works! BUT...not on Safari or Mobile Safari.
Here is my jQuery. I assume if first click is not working that I must add listener before the first click?? Can the event listeners be added on page load BEFORE the function to prevent default click, etc.?
<script>
// BEGIN FUNCTION TO CAPTURE AND INSERT CONTENT
$(document).ready(function () {
// PREVENT DEFAULT LINK ACTION
$('.bio').click(function (e) {
e.preventDefault();
// ADD LISTENER TO EACH ITEM BY CLASS
var list = document.getElementsByClassName("bio");
for (let i = 0; i < list.length; i++) {
list[i].onclick = moveToDiv;
}
// FUNCTION TO MOVE TO LOCATION
function moveToDiv() {
document.location = "#performbio";
}
// STORE the page contents
var link = $(this).attr("href");
// load the contents into #performbio div
$('#performbio').load(link);
});
});
</script>
Here is the HTML with links in unordered list
<!-- CONTRIBUTING ARTISTS LIST AND BIOS -->
<section id="artists">
<h2>Contributing Artists</h2>
<ul class="cols">
<li><a class="bio" href="performers/first-last.html">First Last</a></li>
<li><a class="bio" href="performers/first-last.html">First Last</a></li>
<li><a class="bio" href="performers/first-last.html">First Last</a></li>
</ul>
</section>
Here is HTML of Section where code is being inserted by function
<!-- Performer Bios Dynamically updated -->
<section id="performbio">
</section>
Here is div contents that are being inserted
<div class="artistbio">
<p class="artistname">First Last</p>
<img class="artistimg" src="performers/img/name.jpg">
<p>lots of text here</p>
</div>
If I understand it right, you want to scroll to the section where the details appear on clicking any item in the list but through js and not HTML. In that case, you would add an onclick listener on to the list elements like so:
listElement.onclick = moveToDiv;
The function:
function moveToDiv() {
document.location = "#performbio";
}
A simple way to add a listener to all of the elements:
var list = document.getElementsByClassName("bio");
for (let i = 0; i < list.length; i++) {
list[i].onclick = moveToDiv;
}
For the edited post, you need to move the function definition out of the document.ready function. you would change the script to:
// FUNCTION TO MOVE TO LOCATION
function moveToDiv() {
document.location = "#performbio";
}
$(document).ready(function () {
// PREVENT DEFAULT LINK ACTION
$('.bio').click(function (e) {
e.preventDefault();
// ADD LISTENER TO EACH ITEM BY CLASS
var list = document.getElementsByClassName("bio");
for (let i = 0; i < list.length; i++) {
list[i].onclick = moveToDiv;
}
// STORE the page contents
var link = $(this).attr("href");
// load the contents into #performbio div
$('#performbio').load(link);
});
});
Another Solution: Using scrollIntoView
First, get all the elements into a variable using querySelectorAll
var elements = document.querySelectorAll(".bio");
Then create a function, for the scrolling part:
function scroll(element) {
element.scrollIntoView();
}
Then just add the onclick listener:
for (let i = 0; i < elements.length; i++) {
elements[i].addEventListener('click', function() {
scroll(elements[i]);
});
}
I found it very frustrating to try to accomplish these two tasks so instead of a jQuery solution I opted for a CSS solution.
I populated my DIV with all the php includes, gave them unique id's for the anchors to work and then used CSS to hide them by default until clicked and it works like a charm....shows only what I need to show and goes there like an anchor is supposed to.
I must thank Ghost for all of your help and efforts to try and solve this via jQuery. You were very kind and generous.
Here is the code I used:
My collection of links.
<li><a class="bio" href="#artist-name1">Name 1</a></li>
<li><a class="bio" href="#artist-name2">Name 2</a></li>
which anchors to these divs
<div class="bio-container" id="artist-name1">
<?php include('performers/name-lastname.html'); ?>
</div>
<div class="bio-container" id="artist-name2">
<?php include('performers/name-lastname.html'); ?>
</div>
Then I use this CSS to hide those divs until the anchors are clicked.
I'm using [id*="artist-"] to target only links with such text...very easy. Not ideal for a massive list...but mine is not so large so it will do for this situation.
[id*="artist-"] {display: none;}
[id*="artist-"]:target {display: block;}

When creating a 'query parameter' can it be specified to a container tag rather than just individually to each 'a href' tag

When creating a 'query parameter' can it be specified to a container tag rather than just individually to each 'a href' tag.
I am using a menu [MenuA.html] with many 'a href' links each containing the same 'query parameter'.
MenuA Child Page1
MenuA Child Page2
MenuA Child Page3
......etc.
Is it possible to instead dispense with having to add the "?MyRedictedFrom=MenuA" 'query parameter" to
each individual 'a href' link and instead do one of three things?
(A - good) Globally for the page, declare all 'a href' when clicked append that common 'query parameter'.
(B-better) That restricted to one container only, say that of the 'article tag', all of the 'a href'
contained only within that container append the desired common 'query parameter'.
(C-best) Given I am using more that one set of 'nav tag' containers [a content section of links and,
another bottom section of site navigation links each enclosed in 'nav tag(s)'] the nicest solution, if
possible, would be to target the 'a href' appending to take place in just one of the 'nav tag' sections
specified.
Gratitude #CertainPerformance. I wish not so much to redo the working code on those given single common child pages I know can be invoked from either a parent MenuA or a parent MenuB. But rather, going back to my initial question in this context, using the already working outgoing 'query parameter' string(s) appended now individually to each parent 'a href', I only wish optionally (A)or(B)or(C) to have the 'query parameter' string auto set via the page load itself or by specifying it to a tagged container. I will add my present working code to my question area as comments are limited.
zMenuA.html
<!doctype html>
<html>
<head>
<title>zMenuA.html [Acknowledgement #Andu Andrici]</title>
</head>
<body>
<article>
<nav>
zMenuA.html invoking zSameTarget.html
<!-- other links as well -->
</nav>
</article>
<nav></nav>
</body>
</html>
zMenuB.html would almost be a duplicate of zMenuA except essentially its appended 'query parameter' string would be: ?redictedFrom=zMenuB. It is zMenuA and zMenuB I would hope to modify to have the parameter string added to the (A-good) document onload, or (B-better) the article tag, or (C-best) the first nav tag.
The common child in this case seems need no change and is shown in its functional working completion below:
<!doctype html>
<html>
<head>
<title>zSameTarget.html [Acknowledgement #Andu Andrici]</title>
<style></style>
<script type="text/javascript">
var MyAppendedUrlMarker = window.location.search
if (MyAppendedUrlMarker === '?redictedFrom=zMenuA') {
onload = function () {
var MyElement =
document.getElementById("MyDisplayOnOff0").style.display = "inline";
var MyElement =
document.getElementById("MyDisplayOnOff1").style.display = "none";
}
}
if (MyAppendedUrlMarker === '?redictedFrom=zMenuB') {
onload = function () {
var MyElement =
document.getElementById("MyDisplayOnOff0").style.display = "none";
var MyElement =
document.getElementById("MyDisplayOnOff1").style.display = "inline";
}
}
</script>
</head>
<body>
<p style="white-space:pre-wrap;">
This is the child page 'zSameTarget.html' with this content showing
the same; BUT, at the bottom, with different content [a navigation link]
being visible and active, solely dictated by which parent page invoked
this page. To whit, whether in opening this page, an [a href ....] was
clicked on 'zMenuA.html', or if it came from a click originating from
'zMenuB.html' instead. NOTE: running this page alone will show two links.
It is meant to show only one link. Therefore, first open 'zMenuA.html'
or 'zMenuB.html' and then link to this page from either one of them. As
indicated, depending on the page chosen, one will find it has produced a
different content [link in this case] visible at the bottom.</p><br/>
<div>
<a id="MyDisplayOnOff0" href="./Menu%20-%20Rivers%20of%20Mind%20and%20Heart.html">Rivers of Mind and Heart</a>
<br/>
<a id="MyDisplayOnOff1" href="./Menu%20-%20Of%20Lila%20and%20the%20Void.html">Of Lila and the Void</a>
</div>
</body>
</html>
With Javascript, you might consider using event delegation - when an a inside a particular container is clicked, save that container's name (like MenuA) in SessionStorage, and then you can try to retrieve that SessionStorage value when on the other page. For example:
document.addEventListener('click', ({ target }) => {
if (!target.matches('.menu > a')) {
return;
}
const menuName = target.parentElement.id;
alert('Clicked on ' + menuName);
sessionStorage.redirectedFrom = menuName;
});
<div id="MenuA" class="menu">
MenuA Child Page1
MenuA Child Page2
MenuA Child Page3
</div>
<div id="MenuB" class="menu">
MenuB Child Page1
MenuB Child Page2
MenuB Child Page3
</div>
And then, on each of the child pages, on pageload, check to see if something's in redirectedFrom:
const { redirectedFrom } = sessionStorage;
// do something with redirectedFrom, if it exists
sessionStorage.removeItem('redirectedFrom');
If the query parameter is used by the server, and not by the client, then you can change the href onclick instead:
document.addEventListener('click', ({ target }) => {
if (!target.matches('.menu > a')) {
return;
}
const menuName = target.parentElement.id;
const newHref = `${target.href}?redirectedFrom=${menuName}`;
target.href = newHref;
alert('Clicked on ' + menuName + ', redirecting to ' + newHref);
});
<div id="MenuA" class="menu">
MenuA Child Page1
MenuA Child Page2
MenuA Child Page3
</div>
<div id="MenuB" class="menu">
MenuB Child Page1
MenuB Child Page2
MenuB Child Page3
</div>

How can i change the innerHTML content when clicking on an image?

I'm quite new in coding, trying to educate myself because i'm interested. So, sorry if it's going to be a bit dumb question or not so specific or not really correct...
On my "practicing site" i'm having some navigation links, which are referring to different innerHTML contents (like different pages). I used the 'onClick' event to make them show up, for example like this:
<div class="nav" onClick="changeNavigation('a')">menu</div>
It works with texts perfectly, but my problem is that i don't know how to make the same with an image. So when i click on the image, i want to be redirected to that innerHTML page, like i did it with the text based button. I tried to do it like these two ways, but none of them worked.
<img src="picture.png" onClick="changeNavigation('a')" />
<div onClick="changeNavigation('a')"><img src="picture.png"></div>
Is it possible to make this with an image and the 'onClick' event? Or how else can i make this work?
By the way this is my script to make innerHTML show up:
<script>
function changeNavigation(id) {
document.getElementById('main').innerHTML = document.getElementById(id).innerHTML
}
</script>
I also tried to add my image an id that says 'main' like in the script this way, but with no result.
<img id="main" onClick="changeNavigation('f')" src="picture.png" />
Can you help me please? I would appreciate any answer, because i already searched about this and i didn't find anything that could've helped solve my problem and i'm really stuck right now.
(Sorry if my english isn't the best, it's not my native language.)
I have updated my answer to what you want. You need to the divs id you want to display as a parameter to the function you use for onclick. A sample is below.
var divs = ["Menu1", "Menu2", "Menu3", "Menu4"];
var visibleDivId = null;
function toggleVisibility(divId) {
if(visibleDivId === divId) {
visibleDivId = null;
} else {
visibleDivId = divId;
}
hideNonVisibleDivs();
}
function hideNonVisibleDivs() {
var i, divId, div;
for(i = 0; i < divs.length; i++) {
divId = divs[i];
div = document.getElementById(divId);
if(visibleDivId === divId) {
div.style.display = "block";
} else {
div.style.display = "none";
}
}
}
.main_div{text-align:center; background: #00C492; padding:20px; width: 400px;}
.inner_div{background: #fff; margin-top:20px; height: 100px;}
.buttons a{font-size: 16px;}
.buttons a:hover{cursor:pointer; font-size: 16px;}
img {cursor:pointer}
<div class="main_div">
<div class="buttons">
<img src="http://www.clker.com/cliparts/J/g/2/D/p/I/one-hi.png" width="50px" onclick="toggleVisibility('Menu1');"> <img src="http://www.clker.com/cliparts/E/x/J/x/m/z/blue-number-two-hi.png" width="50px" onclick="toggleVisibility('Menu2');">
<img src="http://www.clker.com/cliparts/L/H/T/b/g/N/three-md.png" width="50px" onclick="toggleVisibility('Menu3');">
<img src="http://www.clker.com/cliparts/v/G/G/A/D/s/four-md.png" width="50px" onclick="toggleVisibility('Menu4');">
</div>
<div class="inner_div">
<div id="Menu1">I'm container one</div>
<div id="Menu2" style="display: none;">I'm container two</div>
<div id="Menu3" style="display: none;">I'm container three</div>
<div id="Menu4" style="display: none;">I'm container four</div>
</div>
</div>
You can just keep all of the sections as children of #main, and selectively show them when the section button in clicked. E.g.,
HTML
<nav>
<button type="button" data-index=0>Show one</button>
<button type="button" data-index=1>Show two</button>
<button type="button" data-index=2>Show three</button>
</nav>
<main id="main">
<section>One</section>
<section class="hidden">Two</section>
<section class="hidden">Three</section>
</main>
CSS
.hidden {
display: none;
}
JavaScript
const buttons = Array.from(document.querySelectorAll('button'));
const contentBlocks = Array.from(document.querySelectorAll('section'));
function hideSections (arr) {
arr.forEach(a => {
a.classList.add('hidden');
});
}
function showSection (index, sections) {
// Just a basic check, not exhaustive by any stretch
if (index !== undefined && sections !== undefined) {
hideSections(sections);
sections[index].classList.remove('hidden');
}
}
buttons.forEach(button => {
button.addEventListener('click', () => {
const contentBlocks = Array.from(document.querySelectorAll('section'));
const index = button.getAttribute('data-index');
showSection(index, contentBlocks);
});
});
Obviously you'll have to adjust your selectors for your use case, but Here's a pen
Here's a GitHub Gist pointing to some examples I created on JSFiddle based off of your specific use case (Stack Overflow doesn't let me post links to JSFiddle directly without including code here, but it's easier to follow along/experiment entirely in JSFiddle):
https://gist.github.com/andresn/f100386f06ee28e35bd83c62d9219890
More advanced stuff:
Ideally, you'd use what's called event delegation instead of adding an onclick to every anchor (DRY = Don't Repeat Yourself is good to always keep in mind while programming and so is KISS = Keep It Simple Silly). Here is a resource explaining event delegation:
https://davidwalsh.name/event-delegate
You can even take this further by preloading all your images so they load behind the scenes when the user first loads the page:
https://perishablepress.com/3-ways-preload-images-css-javascript-ajax/

Sub-navigation bar

I was wondering how would I be able to make a sub nav where only the sub nav changes once I've clicked one of the links in the navigation bar instead of the whole page refreshing if you can help me much appreciated
http://jsfiddle.net/qrn8Q/
Thank you.
HTML Code:
<header class="header">
<div class="container">
<div class="header-primary_container">
<a class="header_brand" href="#"></a>
<div class="navigation-primary_right">
<div class="navigation-primary">
<nav class="navigation-primary_links"> Home
Designs
About Us
</nav>
</div>
</div>
</div>
</div>
</header>
<nav class="sub_nav">
Home
Sign in
Sign up
</nav>
</div>
What you need to do is to use either Ajax or iFrame. For onclick event of those links, you can write your javascript codes to load the new content.
You can accomplish this with jQuery. check out my code. it's pretty simple and easy:
http://jsfiddle.net/mELsr/
$('.nav_icon').click(function() {
$('nav.sub_nav:visible').fadeOut(300); // 1
$('.selected').removeClass('selected'); // 2
var classKey = $(this).attr('id'); // 3
$('nav.'+classKey+'_sub_nav').fadeIn(500); // 4
$(this).addClass('selected'); // 5
return false; // 6
});
In plain english: whenever on of the .nav_icon's is clicked, fade out the visible sub_nav (1) and remove .selected class from the .nav_icon that was selected (2). fetch the clicked item's id attribute (3) and find the sub_nav related to it and fade it in (4) and then add .selected class to the clicked item (5). at last return false; in order to ignore the links default behavior (6).
Hope it help you get started.

jQuery toggle() animating when I don't want it to?

I've got three elements with IDs "albums", "about", and "contact", and three links to show/hide them via the toggle() function, with IDs "togglealbums", "toggleabout", and "togglecontact". I only want one of these elements to be able to be seen at any time, so I wrote the following functions:
$('#togglealbums').click(function() {
if( $('#about').is(':visible') ) {
$('#about').toggle(function() {
$('#albums').toggle();
});
} else if( $('#contact').is(':visible') ) {
$('#contact').toggle(function() {
$('#albums').toggle();
});
} else {
$('#albums').toggle();
}
});
$('#toggleabout').click(function() {
if( $('#albums').is(':visible') ) {
$('#albums').toggle(function() {
$('#about').toggle();
});
} else if( $('#contact').is(':visible') ) {
$('#contact').toggle(function() {
$('#about').toggle();
});
} else {
$('#about').toggle();
}
});
$('#togglecontact').click(function() {
if( $('#albums').is(':visible') ) {
$('#albums').toggle(function() {
$('#contact').toggle();
});
} else if( $('#about').is(':visible') ) {
$('#about').toggle(function() {
$('#contact').toggle();
});
} else {
$('#contact').toggle();
}
});
First of all, if these are wildly inefficient or there is an easier way to do this, please let me know.
What I've found is that if none of the three DIVs is visible, clicking one of the toggle links will show/hide the respective div with no animation. However, if one of the DIVs is visible, clicking another toggle link will cause the div to shrink and fade and the new one expands and fades in, which I don't want (at least for now). This can be seen here: http://new.e17.paca.arvixe.com.
Can anyone tell me why this is happening?
Thanks!
EDIT:
Markup is here:
<body>
<div id="main">
<div id="nav">
<div id="menu">
<ul>
<li>Albums</li>
<li>About Me</li>
<li>Contact</li>
</ul>
</div>
</div>
<div id="albums">
Albums go here
</div>
<div id="about">
About info goes here
</div>
<div id="contact">
Contact info goes here
</div>
</div>
</body>
Your shrink-and-fade was happening because, if .toggle() is given a callback function, it assumes you want to animate the toggle instead of just switching it on/off. (According to the docs, as of this writing, that's only supposed to happen when you provide a duration. I've submitted a bug report about this.)
See http://jsfiddle.net/mblase75/byKeP/1/ for a reduced example of this. To solve it, just remove the callbacks and put the same code in the next line of your function.
As for streamlining your code, classes are your friends. HTML:
toggle albums
toggle about
toggle contact
<div class="toggleblock" id="albums">ALBUMS</div>
<div class="toggleblock" id="about">ABOUT</div>
<div class="toggleblock" id="contact">CONTACT</div>
Note the data- attributes, which jQuery will parse and make accessible through the .data() method. This makes it easy to store a unique div ID on the hyperlink itself, which in turn streamlines our JavaScript immensely. JS:
$('.togglelink').on('click',function(e) {
var id = $(this).data('block');
$('#'+id).toggle().siblings('.toggleblock').hide();
});​
http://jsfiddle.net/mblase75/byKeP/