I've never asked a question here, but I've made use of many answers so am hoping that the effect I'm hoping to achieve will also help others looking to achieve the same effect.
I'm currently working on a client's website and have uploaded it to my dropbox for this question:
http://dl.dropboxusercontent.com/u/62164771/stage/cw/index16042013.html
It currently uses a few different scripts to achieve the following:
(this script is in the head area)
The navigation menu is fixed, and when you click on a menu link, the page scrolls to the relevant section.
When the page scrolls to the relevant section (after being clicked on), a class (.act) is added to the active menu link. The .act class is also added when the user scrolls up and down in the page with their mouse/track pad or whatever.
(this script is at the bottom of the page)
Another effect is also added to the nav bar links:
When you hover over a nav item, a nav menu indicator arrow (a div with a background image of an arrow) slides across to the hovered link.
So this is what I want to happen
Currently the nav menu indicator arrow only slides on hover. I want it to slide to the active link when it is clicked and stay there until the user hovers on another link. My current script is a little buggy with the menu indicator not always sliding to the active link.
I also want the nav menu indicator arrow to slide to the active link when the user scrolls through the page.
Is this achievable?
Relevant Scripts
Script 1 - scroll smoothly to section and activate 'act' class when scrolling:
<script type="text/javascript">
jQuery(document).ready(function( $ ) {
$('nav a').on('click', function() {
var scrollAnchor = $(this).attr('data-scroll'),
scrollPoint = $('section[data-anchor="' + scrollAnchor + '"]')
.offset().top + 1;
$('body,html').animate({
scrollTop: scrollPoint
}, 500);
return false;
})
$(window).scroll(function() {
var windscroll = $(window).scrollTop();
if (windscroll >= 100) {
$('#wrap section').each(function(i) {
if ($(this).position().top <= windscroll + 200) {
$('nav a.act').removeClass('act');
$('nav a').eq(i).addClass('act');
}
});
} else {
$('nav').removeClass('fixed');
$('nav a.act').removeClass('act');
$('nav a:first').addClass('act');
}
}).scroll();
})
</script>
Script 2 - For sliding the main-menu-indicator to the position of the hovered and active links
<script type="text/javascript">
$('#header')
.css('position', 'relative')
.append(
$('<div>').attr('id', 'main-menu-indicator')
)
menuHover = function(which){
if(which==null)
which = $('ul#main-menu a.act')
$('#main-menu-indicator')
.stop(true, false)
.animate({
left: ($(which).offset().left - $('#header').offset().left +
$(which).width()/2 + parseInt($(which).css('paddingLeft')) -
$('#main-menu-indicator').width()/2 )
}, 500)
}
$('ul#main-menu a')
.hover(
function(){
menuHover(this)
},
function(){
menuHover(null)
}
)
</script>
You can use Bootstrap ScrollSpy to get the desired effect, it might be easier to implement than writing your own solution. You could start the animation using the activate event.
In your case you could set <a href="#top">, you currently have a section and an article with the same id, you should get rid of one of those as it is invalid html to have more than one element with the same id, and it might break things. For example keep the id on the article: <article class="top area" id="top">. Include the ScrollSpy script on the page and add:
$('.header').scrollspy({activate: function() {
// Add your logic here.
}
});
Inside the activate function $('nav li.active') will give you the currently active li, with that info you should be able to work out where to move your arrow, and you can then run your smooth scrolling arrow code to move the arrow to the right place.
Now ScrollSpy takes care of calling activate when the user scrolls somewhere, and you react on that by moving the arrow to the right place.
Related
Create a html page for mobile some part of content is showing on Menu bar.
Only the bottom content is showing on menu bar how to avoid it ?
and also I want to disable scroll-bar when menu button is clicked & enable when content is touched using Mobile.
I tried below code but its disabliling but not enabling scrollbar when content screen is clicked on mobile :(
My Javascript :
$(document).ready(function() {
scrollTopPos = $( document ).scrollTop();
allowScrolling = true;
$(document).scroll(function() {
if(allowScrolling === false) {
$( document ).scrollTop( scrollTopPos );
} else {
}
});
$( "#mobile-toggle" ).click(function() {
$('body,html').css('overflow', 'hidden');
$("#divCls").css('display','None')
});
$(document).on('touchmove', function(e) {
e.preventDefault();
showDiv()
});
});
function showDiv() {
document.getElementById('divCls').style.display = "block";
}
It's hard to tell without the full code, but in terms of keeping the menu at the front you can just use CSS to se the Z-index of the DIV. In terms of the scroll, add a CSS rule trigger within your JavaScript to set Overflow to Hidden then set it back to scroll when you click the close button.
Also, if only parts are spilling over then be weary of the page size, if you're using a slide in menu that is hidden to the side then slides the whole page over, then mobile users can swipe it shut but the open button will not work unless you use the jquery swipe functionality so again, the z index and a bit of doodling with the script to make the menu sit over the page would fix this. Again, more script would be handy :P
I replaced the scrolling animation of my one page website with another scrolling animation which changes the URLs when you use the topbar (it was build in foundation)
While the URLs now change when I click an item in the topbar all the other links or clickable elements on my page make it scroll back to the top of the page.
For example when I try to click the next/prev buttons of my slider it scrolls back to the top of the page as if I clicked on Home.
Can someone see whats wrong with the code for the animation?
$(document).ready(function () {
$('a[href^="#"]').click(function () {
var target = $(this.hash),
hash = this.hash;
if (target.length == 0) {
target = $('a[name="' + this.hash.substr(1) + '"]');
}
if (target.length == 0) {
target = $('html');
}
$('html, body').animate({
scrollTop: target.offset().top
}, 500, function () {
location.hash = hash;
});
return false;
});
});
PS: When I scroll manually the URLs don't change when I go down to the next page. If anyone has a fix for this I'll be happy to here from you! (I tried using history.js but that only seems to work if you have a server, which I don't)
//* EDIT *//
I just found out it's not all links that make it scroll to the top of the page, just the buttons of my orbit slider and the menu button when the topbar is collapsed
//EDIT 2//
The URL now changes when I scroll to the next page!
The only problem I am seeing right now is that the buttons of my orbit slider and the menu button of the collapsed topbar act the same as my home button (makes the page scroll all the way back to the top) for some reason.
So the last thing I need to do is get the buttons working again. Making the menu button expand the topbar and making the next and prev buttons of my slider work as normal
If you only want to change the hash depending on the scrollPosition you are half way there.
You'll need to bind some logic to the scroll event. Here is a fork of your Fiddle where the hash is changed on scroll.
When the user scrolls the page we iterate through all .page elements and compare their offset().top against $( document ).scrollTop().
We set the new hash to be the id of the last .page element that has a lower offset().top than $( document ).scrollTop() is.
(I also debounced the function so it doesn't fire constantly when scrolling - you could of course remove that part)
You should however consider that by changing the hash you will jump to the equivalent element. Here is a guide on how to suppress that behaviour.
EDIT:
Here is an updated Fiddle where I implemented the solution from above for suppressing forced scroll on hash change.
I am having a trouble on adding a jquery code to a landing page so that when I scroll down among the sections the relevant sections should be shown in the navbar links by adding a class named clicked. I have added the code snippet that I am currently working on for your reference.. :-)
Any help would be gladly appreciated. :-)
$(document).ready(function(){
$(".link").click(function(event){
------ Scroll code ------------
$(".clicked").removeClass("clicked");
$(event.target).addClass("clicked");
});
});
You don't need to add an onClick event handler for that. The approach you should be using is not that difficult.
First you need to know your current scrolling position, which you can retrieve using:
$(document).scrollTop();
Then you need to know the position of bottom of the visible portion, which is actually the scrolling position + the height of the window:
var btm = $(this).scrollTop() + $(window).height();
Now we need to check if the section is above the bottom portion (that means it's visible), so in order to do that we need to get the position of the section. You can do that by using:
var titlePos = $($(myLink).attr("href")).offset().top;
What happens here is that we're going to look for the section that is referred to by the navbar link and then get it's offset (that's the position of where it's located on the document). You get both the left and top offset, but in this case we only need to get the top offset.
The only thing you need to do know is automate this for all links in your navigation, you can do that for example by doing:
$(".nav li a").each(function() {
var titlePos = $($(this).attr("href")).offset().top;
});
The next step is that we're going to look if the position of the title is above the bottom of the screen, that means that that section is/was visible. You can do that by using:
var btm = $(this).scrollTop() + $(window).height();
$(".nav li a").each(function() {
var titlePos = $($(this).attr("href")).offset().top;
if (titlePos < btm) {
$(this).addClass("visited");
}
});
Now there is only one problem. Sections that are above the screen (= sections you already passed/read) are also above the bottom of the screen, which means that with this code they will be active as well.
To fix that, we need to remove the .visited class from the previous link the moment we know that the next section is visible. You can do that by using:
$(this).parents("li").prev().children("a").removeClass("visited");
This goes to the link just before the link that's active and remove the .visited class from it, so actually only the last visible section is marked as visible.
Now you just add all of this to a scroll event handler and trigger it once to initialize the navigation. The code would become something like:
$(this).scroll(function() {
var btm = $(this).scrollTop() + $(window).height();
$(".nav li a").removeClass("visited").each(function() {
var titlePos = $($(this).attr("href")).offset().top;
if (titlePos < btm) {
$(this).addClass("visited");
$(this).parents("li").prev().children("a")
.removeClass("visited");
}
});
}).trigger("scroll");
Also notice the small change, when I scroll, I first remove the .visited class from all navigation links. I also made a JSFiddle demonstrating this.
I have a accordion menu with very lengthy content. So I need to implement slide effect when accordion content is opened up.
Currently if you open up the first two menu items then the last item shows up the content below the viewport so I need to have the slide up effect for the accordion menu items.
Here is my code
$(document).ready(function () {
//Accordion
$(".menu_body").hide();
//toggle the componenet with class menu_body
$(".menu_head").click(function(){
$(this).next(".menu_body").slideToggle(400);
var plusmin;
plusmin = $(this).children(".plusminus").text();
$(this).children("span.down-arrow").toggleClass("up-arrow");
});
});
DEMO
Explanation:
See there will be N number of accordion menu items with very long table data. And it should allow us to open multiple tabs open up.
Currently it is working fine but the problem is when u click on the menu item which is in the bottom of the page, it is showing up the content down so you wont be able to see it unless you scroll down manually.
This is why I need menu to auto slide scroll to the top of the browser so that content will be seen at a single glance.
I would calculate the clicked button offset and scroll the whole page to that position
minus some amount of pixels (100) just for beauty:
DEMO
$(function () {
//Accordion
$(".menu_body").hide();
//toggle the componenet with class menu_body
$(".menu_head").click(function(){
var thisPOsTop = $(this).offset().top - 100;
$(this).next(".menu_body").slideToggle(400);
var plusmin = $(this).find(".plusminus").text();
$(this).find("span.down-arrow").toggleClass("up-arrow");
$('html, body').stop().animate({scrollTop: thisPOsTop});
});
});
How about trying to auto scroll to the specific element? This 'method' could fire whenever you select an accordian element.
$('html, body').animate({
scrollTop: $("#elementtoScrollToID").offset().top
}, 2000);
The code above will complete the animation in 2 seconds (2000 ms), but you could change that to anything.
This JS Bin seems like exactly what you are looking for.
$('.menu_head').click(function() {
$('html, body').animate( { scrollTop:$(this).offset().top }, 400);
});
Here is my updated jsbin which works fine.
code as below:
$(".menu_head").click(function(){
$(this).next(".menu_body").slideToggle(400);
var plusmin;
plusmin = $(this).children(".plusminus").text();
$(this).children("span.down-arrow").toggleClass("up-arrow");
var scrollvalue = $(this).offset().top;
console.log(scrollvalue);
setTimeout(function(){
$(window).scrollTop( scrollvalue );
},500);
});
I'm using Tiny Scroll Bar from here http://baijs.nl/tinyscrollbar/.
My problem is that when I toggle the folder (i.e: http://prntscr.com/tqf3j), the scroll bar is jumping to the top. I want to stay at a fixed position.
Part of my JavaScript code:
$(document).on('click', '#TreeView a', function() {
CloseFolderOptions();
$('#TreeView a').removeClass('selected');
$(this).addClass('selected');
if ($(this).next('.sub').find('li').length > 0) {
$(this).next('.sub').slideToggle();
oScrollbar5.tinyscrollbar_update();
}
I don't know the position of folders because every user can add a folder.
Try this:
oScrollbar5.tinyscrollbar_update('relative');