Change CSS with JS / jQuery when hash value in URL changes - javascript

I have 6 100vw and 100vh divs on a page and a right aligned fixed nav bar.
Each of these divs has an id# from 1 - 6
The nav bar has 6 list items links which point to the id of the div,
for example:
<ul>
<li id="list-item-1"></li>
<li id="list-item-2"></li>
<li id="list-item-3"></li>
<li id="list-item-4"></li>
<li id="list-item-5"></li>
<li id="list-item-6"></li>
</ul>
I am using scroll spy to nicely 'scroll' to the targeted div.
This nicely places the id value in the ur.
for example:
mywebsite.com/#1
or
mywebsite.com/#2
etc
What I would like to do however is IF the url contains #1 or #2 or whatever number it may be, the list item background changes color.
I originally tried an active/not active class, however, this is done on the scroll and click so a listener for a click won't always work.
I have seen quite a few examples from previous questions on here, however the the closest I could get would be something like this:
function locationChange() {
if(location.hash == "#1") {
$('#list-item-1').css('background-color', '#333333');
$('#list-item-2').css('background-color', '#333333');
} else {
$('#list-item-1').css('background-color', '#ffffff');
$('#list-item-2').css('background-color', '#ffffff');
}
);
window.addEventListener("hashchange", locationChange(), false);
With the above code, the page sometimes loads with list item 1 changed, which is good, it picks up the #1 on page load, however when I click or scroll through the page, the others are not picked up.
(I have only supplied a small amount above, my actual code applies this to all list items.)
Any help / suggestions / example code would be greatly appreciated.

Without having a working example, I believe the issue is within this line:
window.addEventListener("hashchange", locationChange(), false);
Adding a listener is a right course of action, but you are calling your function when you are defining the listener. Changing locationChange() to locationChange will not immediately invoke the function and instead pass a handle to the function:
function locationChange() {
if(location.hash == "#1") {
$('#list-item-1').css('background-color', '#333333');
$('#list-item-2').css('background-color', '#333333');
} else {
$('#list-item-1').css('background-color', '#ffffff');
$('#list-item-2').css('background-color', '#ffffff');
}
);
window.addEventListener("hashchange", locationChange, false);

Related

Moving the screen scroll position after page jumps to anchor point?

I have a menu on a single webpage whose links move the page to the section with the corresponding ID. However, there is a sticky header that is covering the top part of each section, so I want to scroll slightly to compensate.
I'm trying to determine a way to scroll the page by 50px after the page moves to a section. I tried doing a .click() event listener on each link, but it appears that the page is moved after the callback is issued, negating my attempt to scroll.
My code looks like the following:
HTML:
<ul id="menu">
<li id="menu-item-1">1</li>
<li id="menu-item-2">2</li>
<li id="menu-item-3">3</li>
<li id="menu-item-4">4</li>
</ul>
JS: (the two interior lines work in the console but not in the page code itself)
$('#menu-item-1 a').click(function(){
var y = $(window).scrollTop();
$(window).scrollTop(y-50);
});
Is there a way to listen for a link action to be completed, then run my scroll code?
did you try setting a timeout, it will have a flicker effect though (unnoticeable)
also you can change your click event to handle all the a tags within li item like this
$('li > a').click(function(){
setTimeout(function(){
var y = $(window).scrollTop();
$(window).scrollTop(y-50); }, 1);
});
here is a sample fiddle for you https://jsfiddle.net/fxabnk4o/16/
As you observed:
but it appears that the page is moved after the callback is issued, negating my attempt to scroll
This happens because your events attached to anchor tag will be executed before the anchor tags default behaviour.
You are using id so you can use it to scroll also via javascript.
Here is a sample which I have tried out:
http://plnkr.co/edit/FzHYaxMCeOMTvWurtNRe?p=preview
<ul id="menu">
<li id="menu-item-1">1</li>
<li id="menu-item-2">2</li>
<li id="menu-item-3">3</li>
<li id="menu-item-4">4</li>
</ul>
function handleClick(e, scrollElemId){
e.preventDefault();
window.scrollTo(0,document.getElementById(scrollElemId).offsetTop+50);
}

jquery menu slideshow hover function loading too fast

I am currently making a website that includes a menu navigation almost identical to the one found at fotopunch.com only instead of pointing down it points up. Anyways, I wrote the code using jquery/javascript for the menu and it works but I am wondering if there is a way to make it so that the hover function doesn't take effect for a specified amount of time. That way when you hover quickly over an item it doesn't cause the page to load unnecessarily. If anyone has any suggestions I would greatly appreciate it.
Below is a copy of part of my code to create the menu navigation. Another issue I am having is if you hover over too many navigation items in a row the arrow lags behind. I am hoping that by creating a wait time before the hover function takes effect that it would mostly correct this issue.
$("div#menu .reps").hover(function() {
if(current_slide != "reps"){
$(".arrow").animate({"left":"135px"});//move the arrow
if(current_slide == "clients"){
$(".clients_display").stop(true, true).fadeOut().hide();
$(".reps_display").fadeIn().show();
current_slide = "reps";
}
else if(current_slide == "services"){
$(".services_display").stop(true, true).fadeOut().hide();
$(".reps_display").fadeIn().show();
current_slide = "reps";
}
else{
$(".training_display").stop(true, true).fadeOut().hide();
$(".reps_display").fadeIn().show();
current_slide = "reps";
}
}
});
I think that something that you can do, although there is probably a better way is:
declare a function where you place all the code with a condition:
function hoverFunc(option)
{
if($(option).is(':hover'))
{
all the code to show the menu
}
}
And on the over function you do:
$("div#menu .reps").hover(function() {
setTimeout("hoverFunc('"+getOptionName+"')",milliseconds);
});
The idea is: when over, set a timeout and when the timeout is reached, check if the mouse is over and then do whatever you want, the hardest point is to pass the reference to the function, but you can pass the name of the item just getting it from html or a rel attribute.
But if you dont need the reference it is really ease, just call the function and check the element.
There is another option that maybe is more interesting for you. You can add a delay to the all the effects and add a stop(true) before, this way, if the user change the tag fast, the events will be cancelled, but it will change if the user goes through an option fast and goes out of the menu.
You an use the delay on some of your calls such as:
$(".reps_display").delay(100).fadeIn().show();
Or you can make some of the show and hide have a longer duration: show(2000) for instance.

fadeIn as callback function after fadeOut doenst work as expected

In my HTML a#navInnerMapR and a#navInnerMapL are contained within div#navTwo.
The following code is within a function. When called, I need the function to fadeOut any visible links in div#navTwo, pause for a moment, and then fadeIn a#navInnerMapR.
$('div#navTwo a').fadeOut(200, function() {
$('a#navInnerMapR').delay(100).fadeIn(200);
});
The code fades out the links but doesn't fade anything in. I thought that they delay would only start once the fadeOut finishes, however changing the delay value to 1000 makes it sometimes work but its very buggy. Thanks
UPDATE Here is a fiddle showing that the hidden link starts to be shown before the visible is hidden: http://jsfiddle.net/jamesbrighton/d9QKr/5/
UPDATE Apologies, my question doesnt include the full details of what I need to achieve. I simplified it as I thought I just had some sort of sytax issus that could be easily fixed.
div#navTwo actually contains 3 links. At any point (other than the delay before animations run) only 1 link is visible. I need to be able to call a function that will hide either of the other 2 links that are being shown, and then show a#navInnerMapR.
Different events will call this function, so either of the 2 links that arn't a#navInnerMapR may be visible. Thanks
UPDATE I think this fiddle illustrates the issue. Ive created 2 div.nav's to illustrate different states. Ive hidden different links with inline CSS in each one. JavaScript will be showing and hiding the links in my div repeatedly, so the same div will look like each example at different times.
Ive created 2 triggers to illustrate that different events will need to call the function. When you click on a trigger you can see the issue with both examples. The visible divs are not hidden before the a.one is shown. Thanks for your patience!
http://jsfiddle.net/jamesbrighton/dYvMS/24/
Interesting point, if I change $('.nav a.one').fadeIn(1000); to an alert, the alert fires multiple times! No idea why this would be the case!
Edit: Updated answer based on your below comment,
Yes this works as I need, but im not sure it will work for my actual
page. Sorry for my question not being detailed enough. The code
example I gave is simplified. In the actual page their are 3 links
within div#navTwo, at any time only one of them will be visible. I
need to be able to call a function that hides any links and shows a
specific one, but either one of the other 2 links in div#navTwo may be
visible. Thanks
DEMO
HTML: Added class to all links inside navTwo
<div id="navTwo">
Right
Left
Middle
Upper
Lower
</div>
JS:
$('.links').click(function() {
showHide($(this));
});
function showHide($this) {
$this.fadeOut(1000, function() {
$('#navTwo a').not($this).delay(1000).fadeIn(1000);
});
}
I think I understood what you need. Try below DEMO and let me know if that is what you want,
DEMO
$('#navInnerMapR').click(function() {
runMeR($(this));
});
$('#navInnerMapL').click(function() {
runMeL($(this));
});
function runMeR($this) {
$this.fadeOut(1000, function() {
$('a#navInnerMapL').delay(1000).fadeIn(1000);
});
}
function runMeL($this) {
$this.fadeOut(1000, function() {
$('a#navInnerMapR').delay(1000).fadeIn(1000);
});
}
As you said, You need the function to fadeOut any visible links in div#navTwo, pause for a moment, and then fadeIn a#navInnerMapR (not other links, only a#navInnerMapR).
$('#navTwo a').click(function(e) {
$(this).parent().children().each(function(i){
$(this).fadeOut('slow', function(){
$('a#navInnerMapR').delay(1000).fadeIn(1000);
});
});
});​
A fiddle is here.

How do I prevent a hash tag link from scrolling the page?

This is driving me absolutely insane. I am building a very customized slider jQuery plugin for a project. One of my requirements is that users must be able to deep link into a specific slide. So naturally all of my slides have hash tags and the navigation links have corresponding hashtags. My problem is that the default functionality of the hash tag links are firing on top of my sliding animation triggered by javascript. That is, instead of sliding to slide 4 it jumps immediately to slide 4 and then animates to slide 8. This is despite using every trick I can think of to prevent the default functionality. Here is the snippet of code in question.
$(slider.nav).bind( 'click', function(event) {
event.preventDefault();
if( !$(this).hasClass('active') ) {
var target = slider.nav.index( $(this) );
slider.animate( target );
}
});
As you can see here I have used event.preventDefault(). I have also tried returning false. No luck whatsoever. Any ideas?
It's hard to say without seeing the HTML. But if it's the way I imagine it, you don't need to keep href="#" in a link if it's not going anywhere. You can use jQuery to just get the next slide, or get slide number 7 without relying on href="#" links.
Instead, you can do something like:
<ul id="slideshow">
<li id="slide_1">Slide 1</li>
<li id="slide_2">Slide 2</li>
<li id="slide_3">Slide 3</li>
</ul>
<a class="slide_nav" data-index="1">1</a>
<a class="slide_nav" data-index="2">2</a>
<a class="slide_nav" data-index="3">3</a>
<a class="slide_nav" data-index="4">4</a>
And in the JS, do something like:
$('.slide_nav').click(function() {
var slides = $('#slideshow li'); // get all slides
var target_id = $(this).data('id') - 1; // Get the current ID and then subtract 1 (index starts at 0)
slider.animate(slides[target_id]);
});
Anyway, that's more like a pseudo-example than anything else, and I'm not sure that would work as-is, but the code should hopefully point you in a direction that would avoid using href="#" and thus avoid the problem you're having now.
Good luck.
Oh jeeze. I'm really sorry. I've wasted everyone's time.
Apparently another developer who was working on the site had added some javascript elsewhere roughly to the effect of
if( window.location.hash ) {
window.location = window.location.hash;
}
No idea why they would add such a thing. Sorry!

navigation with javascript

so i am a begginer and i really need help
so i wrote this function down here;
the objective was to take as parameters an element name , a div tag selector and a php file address,
function navigation($nav,$container,$link)
{
$($nav).click(function(){
$($container).slideUp(500,function(e){
$(this).append("<span>");
$(this).load($link);
});
});
{
$($container).ajaxComplete(function(){
$(this).slideDown(500);
});
}
{
$($container).slideUp(500);
}
}
the usage is simple
navigation("#home",".content","home.php");
navigation("#about",".content","about.php");
navigation("#store",".content","right.php");
the html is just a few <div> one with class=".content" tag and <a> links called #home #about #store the pages in php are just plain html inside them;
now the problem is when i click the link it works but i can find how to make he active link unclickable after it becomes active
and i was about to do a sublist with the same function trying to load a little div under the navigation links that contain links but i cant find how to do
any one of pro's have any idea ???
I can help but it's going to be quite a rewrite.
Firstly, give all your navigation items a class. Inside the nav items (I don't know if they're div, li elements or whatever, put an <a> tag with the src set to the page you want the navigation to load. When done it might look something like below:
<ul id="navigation">
<li class="nav">
<a src="home.php">HOME</a>
</li>
<li class="nav">
<a src="about.php">ABOUT</a>
</li>
<li class="nav">
<a src="right.php">RIGHT</a>
</li>
</ul>
Then use jQuery's onload functionality to bind the click event onload, rather than calling your navigation function 3 times. You grab the src from the child <a> tag of the li clicked.
$(function()
{
$('.nav').click(function()
{
if($(this).hasClass('active'))
{
return false;
}
$(this).siblings('li').removeClass('active');
$(this).addClass('active');
$('.content').slideUp(500).load($(this).children('a').attr('src'),
null,
function(){$(this).slideDown(500);}
);
return false;
});
});
Note the return false; is important to prevent the default action of the link (i.e. sending the user to the other page).
There's several approaches to making a link unclickable. One would be to let the click-event unbind itself:
$('nav')click(function(){
//Your code goes here
$(this).unbind('click');
});
Another would be to manipulate its CSS to hide the element (set display to none).
As for the second part of your question, i don't really get what you want to do. If you want to have a popout under the link, that activates on hover, you can see here how that could be achieved by using an <ul> and its :hover event
http://jsfiddle.net/D3AP2/

Categories

Resources