I'm having some trouble with a script which takes care of smooth scrolling as well as the active state on my main navigation. Plugin: http://tinyurl.com/amz4kob
Please note that the navigation bar is fixed so effectively has no height.
I've got two issues which I can't seem to overcome:
On page load the active state is applied to the contact link. If you scroll down 1px the active state is correctly applied to the home link.
I can't for the life of me figure out how to modify the script to pay attention to anchors within an element with a certain ID? i.e. I only want this script to apply the active state to the elements within the tag.
Any help would be greatly appreciated.
#rrfive
To make life easy here is the commented script:
$(document).ready(function() {
//Get Sections top position
function getTargetTop(elem){
//gets the id of the section header
//from the navigation's href e.g. ("#html")
var id = elem.attr("href");
//Height of the navigation
var offset = 0;
//Gets the distance from the top and subtracts the height of the nav.
return $(id).offset().top - offset;
}
//Smooth scroll when user click link that starts with #
$('a[href^="#"]').click(function(event) {
//gets the distance from the top of the section refenced in the href.
var target = getTargetTop($(this));
//scrolls to that section.
$('html, body').animate({scrollTop:target}, 500);
//prevent the browser from jumping down to section.
event.preventDefault();
});
//Pulling sections from main nav.
var sections = $('a[href^="#"]');
// Go through each section to see if it's at the top.
// if it is add an active class
function checkSectionSelected(scrolledTo){
//How close the top has to be to the section.
var threshold = 54;
var i;
for (i = 0; i < sections.length; i++) {
//get next nav item
var section = $(sections[i]);
//get the distance from top
var target = getTargetTop(section);
//Check if section is at the top of the page.
if (scrolledTo > target - threshold && scrolledTo < target + threshold) {
sections.removeClass("active");
section.addClass("active");
}
};
}
//Check if page is already scrolled to a section.
checkSectionSelected($(window).scrollTop());
$(window).scroll(function(e){
checkSectionSelected($(window).scrollTop())
});
});
The plugin you're using checks the position of the <div class="section"></div> elements on the page, but because you've made them display:none;, all the sections are returning "0 pixels" from the top of the page, and since the "CONTACT" section is the last on the page, it's stopping there.
So, simply remove display:none; from .section in your CSS and it'll work fine.
.section {
/*display: none; <-- Comment this line out. */
height: 100%;
min-width: 990px;
}
Related
I've made a game website that has horizontal and vertical scrolling but I want the website to stop or disable scrolling down the page at the "second arrows" but be able to scroll up the page.
basically I've already tried "overflow-y:hidden" but i still want to beable to scroll back up the page
https://codepen.io/54x1/full/qBBdXGP
check out my codepen to see my design
code for where i want it:
var BotOfWin1 = $(window).scrollTop() + $(window).outerHeight();
var BotOfObj1 = $('.main-rules').position().top + $('.main-rules').outerHeight();
if (BotOfWin1 > BotOfObj1)
{
$('.game-section').css({"display": "block"});
} else {
$('.game-section').css({"display": "none"});
}
I don't know your motivation for disabling scrolling below the second arrows (can the user navigate there other than scolling?). So I'll just go with the assumtion, that you simply want to prevent the user from ever getting there.
Just use display: none in CSS to not display the content.
What I would do is:
Do not display the second page element on pageload
.content-second {
display: none;
}
On scrolling, check if the page has been scrolled to the very right. If so: display second page element.
var win = $(window);
var contentWidth = $('.content-first').width();
win.on('scroll', function () {
var scrolledRight = win.scrollLeft() + win.width() >= contentWidth;
if (scrolledRight) {
$('.content-second').addClass('show');
}
});
See this pen for a simplified example.
I have 2 divs on my webpage. first div is "#pattern" (red one), and second on is "#projets".(blue one)
when use scrolls for the first time, the window scrolls automaticaly to the the second div "#projets". I'm using jquery scroll-To plugin.
it works nice, even if when the users scroll with a large amount of scroll there could be on offset from the "#projets" div... If someone has an idea to correct this would be nice, but that's not my main trouble...
Now i'm trying to scroll back to the top of the page ("#pattern" div) as soon as "#pattern" div reappears when scrolling, the red one. so basically it should be as soon as the offset from the top of my screen of my div "#projets" is supperior to 1.
I've tried so many solutions without results, using flags, multiple conditions... it can be the same kind of thing as on this page, but user should be abble to scroll freely inside the page, not scrolling from hash to hash :
http://www.thepetedesign.com/demos/onepage_scroll_demo.html
here is my html :
<div id="pattern"></div>
<div id="projets"></div>
my css :
#pattern {
height:300px;
width: 100%;
background-color:red
}
#projets {
height:800px;
width: 100%;
background-color:blue
}
and my jquery :
var flag=0 ;
$(window).on('scroll',function(){
var top_projets_position = $("#projets").offset().top - $(window).scrollTop();
if((flag==0) && $(window).scrollTop()>1){
$(window).scrollTo('#projets', 500);
flag=1;
}
if($(window).scrollTop()==0){
flag=0;
}
});
here is jsfiddle :
http://jsfiddle.net/jdf9q0sv/
hope someone can help me with this, I can't figure out what I'm doing wrong, maybe a wrong method ! thanks
It looks like you need to track 3 things:
The scroll direction occurs.
The area you are currently viewing.
If scroll animation is currently happening (we need to wait until it's done, or problems will occur).
http://jsfiddle.net/vx69t5Lt/
var prev_scroll = 0; // <-- to determine direction of scrolling
var current_view ="#pattern"; // <-- to determine what element we are viewing
var allowed = true; // <-- to prevent scrolling confusion during animation
var top_projets_position = $("#projets").offset().top + 1;
$(window).on('scroll',function(){
var current_scroll = $(window).scrollTop();
if(current_scroll < top_projets_position && current_view=="#projets" && current_scroll < prev_scroll){
scrollToTarget("#pattern");
}
if($(window).height() + current_scroll > top_projets_position && current_view=="#pattern" && current_scroll > prev_scroll){
scrollToTarget("#projets");
}
prev_scroll = current_scroll;
});
function scrollToTarget(selector){
if(allowed){
allowed = false;
$(window).scrollTo(selector, {
'duration':500,
'onAfter': function(){ allowed = true; current_view = selector;}
});
}
}
This is just a quick solution based on your original code. A better solution would be to do something more Object Oriented (OOP) and track values in an object. Perhaps take an array of elements on object creation, grab all the boundaries and use the boundaries in your scroll handler to determine when to scroll to the next div.
I want a nav to highlight (or something similar) once a user clicks on it AND when a user scrolls to the corresponding section.
However, on my computer when one clicks on any of the nav events after3, only nav event 3 changes. I'm guessing this is because after one clicks on 4 or 5, the scroll bar is already at the bottom of the page, so 4 and 5 never reach the top. The only div at the top is post 3, so my code highlights nav event 3 and ignores the click.
Is there any way I can fix this? Ive tried if statements (only highlight nav event if it's at the top AND the scrollbar isn't at the bottom or the top isn't the last item).
Here is a more accurate fiddle, using a fix below showing what I am talking about. The fix now highlights on scroll, but if you click option 5, it will not highlight.
$('.option').children('a').click(function() {
$('.option').css('background-color', '#CCCCCC;');
$(this).css('background-color', 'red');
var postId = $($(this).attr('href'));
var postLocation = postId.offset().top;
$(window).scrollTop(postLocation);
});
$(window).scroll(function() {
var scrollBar = $(this).scrollTop();
var allPosts = [];
var post = $('.content').offset();
var lastPost = allPosts.legnth-1
var windowHeight = $(window).height();
var bottomScroll = windowHeight-scrollBar;
$(".content").each(function(){
allPosts.push($(this).attr('id'));
});
i = 0;
for(i in allPosts){
var currentPost = "#"+allPosts[i];
var postPosition = $(currentPost).offset().top;
if (scrollBar >= postPosition){
$('.option').css('background-color', '#CCCCCC');
$('#nav'+allPosts[i]).css('background-color', 'red');
};
};
});
I think you've overdone your scroll() handler, to keep it simple you just needs to check if the scrollbar/scrollTop reaches the '.contents' offset top value but should not be greater than its offset().top plus its height().
$(window).scroll(function () {
var scrollBar = $(this).scrollTop();
$(".content").each(function (index) {
var elTop = $(this).offset().top;
var elHeight = $(this).height();
if (scrollBar >= elTop - 5 && scrollBar < elTop + elHeight) {
/* $(this) '.content' is the active on the vewport,
get its index to target the corresponding navigation '.option',
like this - $('.Nav li').eq(index)
*/
}
});
});
And you actually don't need to set $(window).scrollTop(postLocation); because of the default <a> tag anchoring on click, you can omit that one and it will work fine. However if you are looking to animate you need first to prevent this default behavior:
$('.option').children('a').click(function (e) {
e.preventDefault();
var postId = $($(this).attr('href'));
var postLocation = postId.offset().top;
$('html, body').animate({scrollTop:postLocation},'slow');
});
See the demo.
What you are trying to implement from scratch, although commendable, has already been done by the nice folks at Bootstrap. It is called a Scrollspy and all you need to do to implement it is include Bootstrap js and css (you also need jquery but you already have that) and make some minor changes to your html.
Scrollspy implementation steps.
And here is a demonstration. Notice only one line of js. :D
$('body').scrollspy({ target: '.navbar-example' });
So I have a modal window that is causing the page to scroll down. It adds #login-box to the url but that div id is not a set place. I thought about adding a div to the html but that wouldn't work because my menu is sticky and it would cause them to scroll to wherever that div is.
http://onecraftyshop.com and click "login" in the nav menu. You will see what I'm talking about. Then scroll down and click it again and oyu will see that it scrolls down no matter where you are on the page.
Here is the relevant JS of the modal window:
// Load the modal window
$('a.login-window').click(function() {
// Get the value in the href of our button.
var login_id = $(this).attr('href');
// Add our overlay to the body and fade it in.
$('body').append('<div id="overlay"></div>');
$('#overlay').fadeIn(300);
// Fade in the modal window.
$(login_id).fadeIn(300);
// center our modal window with the browsers.
var margin_left = ($(login_id).width() + 24) / 2;
var margin_top = ($(login_id).height() + 24) / 2;
$(login_id).css({
'margin-left' : -margin_left,
'margin-top' : -margin_top
});
return false;
});
I tried changing
var margin_top = ($(login_id).height() + 24) / 2; to
var margin_top = ($(login_id).height() + 24) / .7; and that stopped the scrolling but the box wasn't centered (it was actually cut off at the top of the page) I then thought "oh easy just change the positioning with css", but then that caused it to start scrolling again!
Visit http://onecraftyshop.com and click "login" in the nav menu. The modal window should pop up and the page will scroll. CSS through firebug or dev tool in chrome.
Let me know if you need anything else.
Thanks for helping me sort this one out!
------------CSS for #overlay as requested--------------------------
background: none repeat scroll 0 0 #000000;
height: 100%;
left: 0;
opacity: 0.8;
position: fixed;
top: 0;
width: 100%;
z-index: 9999999;
To stop scrolling on the page, create this javascript function (written in plain javascript):
scrollingToggleIterates = 0;
function toggleScrolling(event){
if(scrollingToggleIterates%2 == 0){
var scrollPosition = document.documentElement.scrollTop;
document.body.className = 'stopScrolling';
document.documentElement.scrollTop = scrollPosition;
}
else{
var scrollPosition = document.documentElement.scrollTop;
document.body.className = '';
document.documentElement.scrollTop = scrollPosition;
}
scrollingToggleIterates++;
}
Then add this class to your css:
.stopScrolling{
height: 100%;
overflow:hidden;
}
Call the toggleScrolling function when you want to prevent scrolling, then call the function again when you want to restart it. I know you're working in JQuery, but you should be able to intermix it with plain JS.
The plugin that scrolls the window down on fragment links is causing this. If you unhide the login menu you can see the window is scrolling down to it's original location. Since this isn't the default browser behavior, return false or event.preventDefault() will not stop this behavior. You will need to see if there's a class you can add to this link that will stop the plugin from scrolling when this link is clicked.
Another option is to not use the href property for the id of the login window. Make it either href="javascript:void(0)" or just href="#". Then use a data attribute like: data-target="loginMenu" and update your javascript to grab the id from this attribute:
var login_id = $(this).attr('data-target');
My ASP.Net application generates an <asp:Table> from the codebehind. What I need is for the header row of that table to slide down the page as the user scrolls past it.
I've tried the following approach using JavaScript:
window.onscroll = function () {
//grab the current scroll position
var scrollY = document.body.scrollTop;
if (scrollY == 0) {
if (window.pageYOffset)
scrollY = window.pageYOffset;
else
scrollY = (document.body.parentElement) ? document.body.parentElement.scrollTop : 0;
}
//grab the position of the header row I want to slide
var head = $("tr[name='headerrow']").offset();
var headtop = head.top;
var headleft = head.left;
//if the user has scrolled past the top of the header row
if (scrollY > headtop) {
//code correctly reaches this point as alerts show
//alert('got here');
//position the header row to the same as the scroll position
$("tr[name='headerrow']").offset({ top: scrollY, left: headleft });
}
}
I can't get the row to move. There are no error message to be seen on the various browsers developer tools.
Any help would be appreciated.
EDIT: I tried calling the offset() function on the children of the row (i.e. all of the <th> elements) like this:
$("tr[name='headerrow']").children().offset({ top: scrollY, left: headleft });
This now works but of course, they're all pushed over to the left because I'm using the left value of the header row itself... I'll keep this updated with my progress but in the meantime any assistance is appreciated as always.
Solution:
Use the children() method on the table row to allow you to change the offset of each of the <th> elements. The left value can be omitted from the offset() method, i.e.
$("tr[name='headerrow']").children().offset({ top: scrollY });
You cannot set the offset to any element. You should use css method and set the top and left parameters.