I have set up some anchors and a little menu up top. when I click a menu item, it will scroll to that anchor.
what I want to do is have a next arrow on the menu to determine the next anchor on my page and scroll to it onClick.
My anchors are #header, #box1 - #box5
I would like to do it with JavaScript if possible.
here is my page
My Page
There is an HTML collection called document.anchors. To go to the next anchor, get the current anchor name from the URL and look for it in document.anchors. If you find it, the next one will be the next index. If you're at the last index, set the anchor to the first. Otherwise, if there is no match, just set it to the first.
This allows you to use any scheme for naming anchors, they will be visited in the order they appear in the DOM.
e.g.
<head>
<!-- Hide script-dependent content -->
<style type="text/css">
.requiresScript-block, .requiresScript-inLine {
display: none;
}
div.spacer {
height: 500px;
border: 1px solid blue;
}
</style>
<script type="text/javascript">
function goToNextAnchor() {
var anchors = document.anchors;
var loc = window.location.href.replace(/#.*/,'');
var nextAnchorName;
// Get name of the current anchor from the hash
// if there is one
var anchorName = window.location.hash.replace(/#/,'');
// If there is an anchor name...
if (anchorName) {
// Find current element in anchor list, then
// get next anchor name, or if at last anchor, set to first
for (var i=0, iLen=anchors.length; i<iLen; i++) {
if (anchors[i].name == anchorName) {
nextAnchorName = anchors[++i % iLen].name;
break;
}
}
}
// If there was no anchorName or no match,
// set nextAnchorName to first anchor name
if (!nextAnchorName) {
nextAnchorName = anchors[0].name;
}
// Go to new URL
window.location.href = loc + '#' + nextAnchorName;
}
// Display script-dependent content if javascript available
document.write(
'\u003Cstyle type="text/css"\u003e' +
'.requiresScript-block {display: block;}' +
'.requiresScript-inLine {display: inline;}' +
'\u003C/style\u003e'
);
</script>
</head>
<body>
<ol>
<li>Go to header
<li>Go to box 1
<li>Go to box 2
<li>Go to box 3
<li>Go to box 4
<li>Go to box 5
</ol>
<!-- Only shown if javascript available -->
<button class="requiresScript-inLine" onclick="goToNextAnchor()">Next</button>
<a name="header"></a><h1>Header</h1>
<div class="spacer">content</div>
<p><a name="box1"></a><p>Box 1</p>
<div class="spacer">content</div>
<p><a name="box2"></a><p>Box 2</p>
<div class="spacer">content</div>
<p><a name="box3"></a><p>Box 3 </p>
<div class="spacer">content</div>
<p><a name="box4"></a><p>Box 4</p>
<div class="spacer">content</div>
<p><a name="box5"></a><p>Box 5</p>
</body>
Something using an onClick in your HTML:
===>
...and then the JavaScript:
var max = 5;
function goToNext() {
var hash = String(document.location.hash);
if (hash && hash.indexOf(/box/)) {
var newh = Number(hash.replace("#box",""));
(newh > max-1) ? newh = 0 : void(null);
document.location.hash = "#box" + String(newh+1);
} else {
document.location.hash = "box1";
}
}
Change max the highest number you want to go (for box1, box2, etc...). Not sure if this will keep the animation, but you can take a look at an example here. Just watch the address bar.
Related
I am creating a collapsible div, which has another collapsible div nested inside:
<button class="collapsible">Expand First Panel</button>
<div class="firstPanel">
<div class="fistPanelContent"> ••• </div>
<button>Expand Second Panel</button>
<div class="secondPanel">
Content of the second panel
</div>
</div>
On click of the first button, the firstPanel div should expand, and upon clicking the nested second button, the secondPanel div should expand.
I've managed to achieve a single expanding div by using overflow: hidden; and a script to change the div's max height:
<script>
var allCollapsibles = document.getElementsByClassName("collapsible");
// Iterate through the collapsibles
var index;
for (index = 0; index < allCollapsibles.length; index++) {
// Add expansion toggle
allCollapsibles[index].addEventListener("click", function() {
// Set max height for collapsible element
var expandableContent = this.nextElementSibling;
if (expandableContent.style.maxHeight) {
expandableContent.style.maxHeight = null;
} else {
expandableContent.style.maxHeight = expandableContent.scrollHeight + "px";
}
});
}
</script>
... but this won't work for the second expanding div, because I've set the first div's max height
How could I get the second div to expand, whilst it's inside the first div?
This is a solution for your markup. It is much simpler to just add and remove a class like show instead of going down the road and doing height calculations. You can then add or remove the class show depending if the item already has the class or not. With css you can hide or show the item.
var allCollapsibles = document.querySelectorAll('.collapsible');
allCollapsibles.forEach( item => {
item.addEventListener("click", function() {
if(this.nextElementSibling.classList.contains('show')) {
this.nextElementSibling.classList.remove('show')
} else {
this.nextElementSibling.classList.add('show')
}
});
});
.firstPanel,
.secondPanel {
display: none;
}
.firstPanel.show,
.secondPanel.show {
display: block;
}
<button class="collapsible">Expand First Panel</button>
<div class="firstPanel">
<div class="fistPanelContent"> ••• </div>
<button class="collapsible">Expand Second Panel</button>
<div class="secondPanel">
Content of the second panel
</div>
</div>
I have created an input section for users to write their own work. I have multiple divs to the side of this and I'd like to change the divs from a left and right arrow that can be clicked.
$(document).ready(function() {
$('.menubody:nth-child(1)').show('slow');
$('.menubody:nth-child(1)').hide('slow');
$('.fa-caret-right').on({
click: function() {
var i = $('.menubody:visible').index();
var len = $('.menubody').length;
var next;
if (i >= 0) {
if (i == len - 1) {
next = $('.menubody:eq(0)');
} else {
next = $('.menubody:eq(' + (i + 1) + ')');
}
$('.menubody:visible').hide();
$(next).show();
}
}
});
});
EDIT:
I have a working example (see fiddle) that changes and changes the content when 'right' is pressed.
How do I make it so the 'left' div moves the content to previous? And add more than one content area to change?
For an example layout of the usage (not jQuery working), please see here.
Use jQuery's .prev() and .next(). If they return a collection of zero length, use .last() and .first() instead to cycle through your content (not sure that you needed this).
$(function() {
$('.tabs-container div').not(':first-child').hide();
$('#tabs li a').click(function() {
var $clickedLink = $(this),
$visible = $('.tabs-container div:visible');
$visible.each(function(){
var $this = $(this),
$parentContainer = $this.parents('.tabs-container').eq(0),
$toShow;
if( $clickedLink.is('.prev') ){
$toShow = $this.prev('div').length ? $this.prev('div') : $('div', $parentContainer).last();
} else {
$toShow = $this.next('div').length ? $this.next('div') : $('div', $parentContainer).first();
}
$this.hide();
$toShow.show();
});
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<ul id="tabs">
<li>Left Arrrow
</li>
<li>Right Arrow
</li>
</ul>
<div class="tabs-container">
<div id="content1">Content for link 1. Should display only when Link 1 is clicked.</div>
<div id="content2">Content for link 2. Should display only when Link 2 is clicked.</div>
<div id="content3">Content for link 3. Should display only when Link 3 is clicked.</div>
<div id="content4">Content for link 4. Should display only when Link 4 is clicked.</div>
</div>
<p>Unrelated text is here. Text in this area is static and should display at all times.</p>
<div class="tabs-container">
<div id="content1-2">Additional content for link 1. Should display only when Link 1 is clicked.</div>
<div id="content2-2">Additional content for link 2. Should display only when Link 2 is clicked.</div>
</div>
<p>More unrelated text</p>
<div class="tabs-container">
<div>A</div>
<div>B</div>
<div>C</div>
<div>D</div>
<div>E</div>
</div>
I think you should use the nth-child() jQuery selector here. Simply increment the value of n every time the button right is clicked and decrease the value of n every time the left arrow is clicked.
$('#left-arrow').on('click', function(){
var i++;
$('main-div:nth-child(i-1)').hide();
$('main-div:nth-child(i)').show();
})
Here's a link to read more : W3 Schools :nth-child() selector
I'm attempting to create a script that, when I click a nav-link, checks what class is attached to that specific link, then hides the current page and displays the page that also contains that specific class.
This script currently switches between 2 pages rather than checking for a page with a class, but I'm sure it'll be simple to add that later (1 line of code).
(function () {
pages = ["home", "about", "portfolio", "misc", "inquire"];
//request = window.location.hash.substring(1);
//Finding page corresponding to clicked link
function SetRequest (link, pages)
{
lookingFor = ".home";
for (var i in pages)
{
if (link.hasClass(("." + pages[i]).toString()))
{
lookingFor = pages[i];
}
}
return ("." + lookingFor).toString();
}
//Hiding all other pages, showing page needed
function ShowCurrentPage (page, pages, lookingFor)
{
for (var i in pages)
{
if (page.hasClass(lookingFor))
{
$(".page.current").animate({opacity: 0});
$(".page.current").removeClass("current");
$(".page").animate({opacity: 1});
$(".page").addClass("current");
}
}
}
$(".nav-link a").click(function(){
ShowCurrentPage($(this), pages, SetRequest($(this), pages));
});
})();
You don't need to make a loop. Just do something like this:
function switchPage(lookingFor)
{
var lookingForDom = $('' + lookingFor); // I assume that lookingFor carries full selector either id or css based
if (lookingForDom.length > 0) // We've found one
{
$(".page.current").removeClass("current").animate({opacity: 0});
lookingForDom.addClass("current").animate({opacity: 1});
}
}
There's also easy way to obtain needed page name, just keep it inside some attribute of link that's beeing clicked and retrive it. Href is designed place for such things (but you need to use id on page-div then). So js would be:
$('.nav-link a').click(function(){ switchPage($(this).attr('href')); });
Also remember to registrate your events either with inside $(document).ready function like so:
$(document).ready(function()
{
$(".nav-link a").click(...);
});
Full example:
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="http://code.jquery.com/jquery-2.1.4.min.js"></script>
<script type="text/javascript">
function switchPage(lookingFor)
{
var lookingForDom = $('' + lookingFor); // I assume that lookingFor carries full selector either id or css based
if (lookingForDom.length > 0) // We've found one
{
$(".page.current").removeClass("current").animate({opacity: 0});
lookingForDom.addClass("current").animate({opacity: 1});
}
}
$(document).ready(function()
{
// Initial switch to hide other pages
$('.page').css({ opacity: 0 });
switchPage('#pageA');
$('.links a').click(function(){ switchPage($(this).attr('href')); });
});
</script>
</head>
<body>
<div id="pageA" class="page">I'm page A</div>
<div id="pageB" class="page">I'm page B</div>
<div id="pageC" class="page">I'm page C</div>
<ul class="links">
<li>Go to page A</li>
<li>Go to page B</li>
<li>Go to page C</li>
</ul>
</body>
</html>
Here's a really simple code that does the trick : http://codepen.io/anon/pen/advjeN
html :
<nav class="nav-link">
<a class="aa" href="#">FIRST LINK</a>
<a class="bb" href="#">SECOND LINK</a>
</nav>
<div class="pages">
<div class="aa page red"></div>
<div class="bb page blue hide"></div>
</div>
CSS :
.page{
height: 200px;
width: 200px;
margin : 20px;
display: inline-block;
}
.red{ background-color: red;}
.blue{background-color: blue;}
.hide{ display: none;}
and jquery :
(function () {
$(".nav-link a").click(function(){
var myclass = '.' + $(this).attr('class');
$('.pages').children().hide();
$(myclass).fadeIn();
});
})();
If put them all in a " pages " div so you can hide them all easely, but if they all at least one class that's the same for all you can simply do $(myclass).hide();
A fixed div (fixed_div) stays at the top to display a Google map inside it. Then a big div (big_div) stays beneath it. The big div has inside it many small divs with class small_div. Each small div has an id small_div_n where n=0,1,2,3.. consecutively. The big div is scrolled beneath the fixed div.
HTML:
<div class="fixed_div" >
</div><!-- end of class fixed_div -->
<div class="big_div">
<div class="small_div" id="small_div_0">
</div><!--end of class small_div -->
<div class="small_div" id="small_div_1">
</div><!--end of class small_div -->
<div class="small_div" id="small_div_2">
</div><!--end of class small_div -->
</div><!--end of class big_div -->
css:
.fixed_div {
position:fixed;
height:100px;
}
.big_div {
padding-top:100px;
}
.small_div {
min-height:80px;
}
Small divs have a variable height property.
If I am able to know that a new small_div has reached the lower part of the fixed div , I can find the corresponding id of the small div and can understand which google map is to be shown in the fixed div through an ajax call.
How to sense that a new small_div has reached the lower part of the fixed div?
EDIT: the big div has a min-height property.
<script>
(function() {
var fixed = $('div.fixed_div');
$(window).on('scroll',function() {
var currentFixedDivPosition = fixed.position().top + fixed.height() + $(window).scrollTop();
var temp, whichOne;
$('div.small_div').each(function(i,s) {
var diff = Math.abs($(s).position().top - currentFixedDivPosition);
if(temp) {
if(diff < temp) {
temp = diff;
whichOne = s;
}
}else {
temp = diff;
whichOne = s;
}
});
console.log(temp, $(whichOne).attr('id') + ' was closest');
});
})();
</script>
Here is a fiddle : http://jsfiddle.net/s3JKk/ , I'm not sure I understood correctly what you wanted, but I hope this will at least give you some start. :) Good Luck!
Hope that following code fulfills the purpose,
I have added a code to dynamically append a small DIV element to a big_div element
Then I added an event listener which detects any new entries to big_div
// the system will append a new DIV when the button is clicked
document.getElementById("add").addEventListener("click", function(){
addDiv();
});
// an event listener which listenes to any new added element to big_div
$('#big_div').on('DOMNodeInserted', function(e) {
// here I am getting the id of the last added element
var newdivid = document.getElementById("big_div").lastChild.id;
document.getElementById("div_status").innerHTML = "new small div added, id: " + newdivid;
});
function addDiv() {
var smalldiv = document.createElement("div");
// here I am setting the id of the newly created DIV to any random string
smalldiv.setAttribute("id", Math.random().toString(36).slice(-5));
smalldiv.appendChild(document.createTextNode("small div"));
document.getElementById("big_div").appendChild(smalldiv);
}
.fixed_div {
position:fixed;
height:100px;
}
.big_div {
padding-top:100px;
}
.small_div {
min-height:10px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="fixed_div" >
fixed div
<p id="div_status">No Status</p>
</div><!-- end of class fixed_div -->
<div class="big_div" id="big_div">
<div class="small_div" id="small_div_0">
div 0
</div><!--end of class small_div -->
</div><!--end of class big_div -->
<button type="button" id="add">Add Small DIV</button>
I am new to JavaScript and actually quite desperate by now
I have an HTML file that:
gets data from an XML file and displays them in various divs (e.g. )
these divs are hidden (by default) by a class name (class='box')
when a link is clicked, I pass the 'href' to the function showContent, remove the #, and then look for an element with that ID in the document.
then I add a new class name ('show') - so that this element shows up!
If you run the code you will see that every time you click on a link a new div is displayed...
So current problems:
replace already shown divs with the new clicked ID so that only one div shows up every time.
How can I avoid inserting the onClick event in every single tag - and make this more automated?
My code is as follows:
function showContent(obj)
{
var linkTo = obj.getAttribute("href");
var newlinkTo=linkTo.replace('#','');
//alert (newlinkTo);
document.getElementById(newlinkTo).innerHTML=" This is where the xml variable content should go";
document.getElementById(newlinkTo).className += " Show";
return true;
}
<a href="#b0" onClick="return showContent(this);">
<div id="text_content"> link2 </div>
</a>
<a href="#b1" onClick="return showContent(this);">
<div id="text_content"> link 1 </div>
</a>
<div class='box' id='b0'> abstract content </div>
<div class='box' id='b1'> introduction content </div>
I'm not usually into using jQuery everywhere, but with it you could just do:
<a class='showContent' data='b0'/>
Your js:
var selected;
$('a.showContent').on('click',function(e){
var toShow = $(this).attr('data');
if(selected!==undefined) selected.removeClass('Show');
selected = $(div+'#'+toShow);
selected.addClass('Show');
});
Not sure if this is what you want, but thought I'd suggest it.
This sort of thing is not hard to do without jQuery.
I would recommend using a hash-bang (#!) for Javascript activated links to keep it separate from other possible links with hashes. (script is at the bottom)
<div id="nav-links">
<a href="#!b0">
<div id="text_content"> link2 </div>
</a>
<a href="#!b1">
<div id="text_content"> link 1 </div>
</a>
</div>
<div class='box' id='b0'> abstract content </div>
<div class='box' id='b1'> introduction content </div>
<script type="text/javascript">
var links = document.getElementById('nav-links').getElementsByTagName('a');
for(var i = 0, link; link = links[i]; i++) {
link.onclick = showContent;
// Hide content divs by default
getContentDiv(link).style.display = 'none';
}
// Show the first content div
if(links.length > 0) showContent.apply(links[0]);
var current;
function showContent() {
// hide old content
if(current) current.style.display = 'none';
current = getContentDiv(this);
if(!current) return true;
//current.innerHTML = "This is where the xml variable content should go";
current.style.display = 'block';
return true;
}
function getContentDiv(link) {
var linkTo = link.getAttribute('href');
// Make sure the link is meant to go to a div
if(linkTo.substring(0, 2) != '#!') return;
linkTo = linkTo.substring(2);
return document.getElementById(linkTo);
}
</script>
There is a WAY cleaner way to do this:
This is just my quick example, it can get EVEN cleaner than this, but this works for your case:
HTML:
link b0
link b1
<div class='box' id='b0'> abstract content </div>
<div class='box' id='b1'> introduction content </div>
CSS:
#b0 { display: none; }
#b1 { display: none; }
a, div.text_content { display: inline; padding: 0 10px; }
JQUERY:
$('.link').click(function(){
var id = $(this).attr("rel");
$('#'+id).slideToggle('slow');
});
Each link would have to have a REL attribute that is the same as the ID of the div element that you are trying to show.
Here is a JSFiddle to this example in action:
http://jsfiddle.net/CUJSM/5/