jQuery scrolling issues with scrollTop - javascript

I am having 2 issues with scrolling, i figured it would just be easier to ask them both in one post.
Before I ask, below is my jQuery code im having issues with.
$("a").click(function() {
if(this.hash){
$("#main").animate({
scrollTop : $("h3[name="+this.hash.substr(1)+"]").position().top - 120
},2000,"easeOutExpo");
}
});
Situation: What I have going on in my page is basically i have a side menu with a couple lists. Each item in each list links to a anchor in my main div section, or my 'content' section. When a list item is clicked, the code above runs and it scrolls to one of the anchors.
Issue 1: When i click on a item in one of the lists, it scrolls down to a anchor which works just fine. But when that same item is clicked again, the main area scrolls back up to the top of the div. My thought to fix this was to check the current 'scrolled to' location of the div, and then not allow the code to run again if the location hadn't changed since the first click but i couldn't get that to work. Any suggestions on how to fix this issue?
Issue 2: Again as stated above, when i click on a item in a list it scrolls down to a anchor. What i then want to be able to to is click on a different list item and have it scroll to that position. The problem is when i click on a different list item, it scrolls to some random position in the main div, positions i haven't even anchored yet. Can anyone explain how I can make it so i can scroll from anchor to anchor?
Note: Please respond by having issue 1 or issue 2 above your explanation so i know which one your referring to. Thanks
EDIT: Thanks to Roko's help i got it working. For future viewers here is the fiddle of a working demo: http://jsfiddle.net/TsUcc/3/ and below is what the finally jquery code looks like
$("a").click(function( e ) {
e.preventDefault();
if(this.hash){
var target = '#'+ this.hash.substr(1);
var destination = $(target).offset().top - 10;
$('#main').stop().animate({
scrollTop : '+=' + destination
}, 1000);
}
});

LIVE DEMO
ISSUE 1:
you probably use something like: goto and you did not prevented the browser default behavior which is simply done by passing the event to the click handler like:
$("a").click(function( e ) {
e.preventDefault();
// .....
});
ISSUE 2
The HTMLelement position you're using is just a passive position of an element relative to it's positioned parent element.
which means that an element can have a position of ie: 30 even if it's at the bottom of your page.
To fix that use
offset().top
Also worth reading: https://developer.mozilla.org/en-US/docs/Web/API/element.getBoundingClientRect
ISSUE 3
H3 elements are not supposed to have a name attribute.
Use an ID for that purpose.
Why?
if you have a nice web and you have some sexy stuff at the bottom of your page, I can send a link to my friend by referencing your web page and the ID in a link like:
example.com#bottomLady
and he'll get immediately my thoughts without the need to scroll your page all the way down.

Related

Scrolling to top inside an accordion

In my page I have 2 scrolls.
One is apparent in the page ( They are not loaded with ajax or something.)
The other one is inside an accordion.
I want these scroll to be always at the top. They have same class names.
With the snipets I can achieve my first goal, scrolling to top in apparent scroll
$('.m-messenger__messages').scrollTop($('.m-messenger__messages')[0].scrollHeight);
As well as with this one
var messageBody = document.querySelector('.m-messenger__messages');
messageBody.scrollTop = messageBody.scrollHeight - messageBody.clientHeight;
However, the scroll inside the accordion menu is not affected by this change.
If I open the accordion and run this snippets it scrolls to top.
So that either
I need to find a way to run this snippet not only to apperent but also all scrolls in the page or
when I click the accordion this javascript code needs to be executed.
I would like to solve this problem with the first solution.
I tried this and I couldn't succeed as well. If I put alert() rather than scrolltop inside this function, I got the alertbox.
$(".m-accordion__item").click(function() {
$('.m-messenger__messages').scrollTop($('.m-messenger__messages')[0].scrollHeight);
});
How can I achieve this goal?
This solved my problem. BTW this is bootstrap4. So that it may apply to any of bootstrap 4 templates.
$('.collapse').on('shown.bs.collapse', function(e) {
$('.m-messenger__messages').scrollTop($('.m-messenger__messages')[0].scrollHeight);
});

Trying to get this wordpress theme to scroll to an id when a link is clicked on a different page

Easiest way to explain it is if you have a look at the site - haloespresso.com.au/working/
If you click the "menu" option in the top menu, it scrolls to the menu id #pg-9-4, which is what I want. On the other pages, the menu is slightly different and the same link is changed to link to the home page with #pg-9-4 added to the end of it. The point here is clearly to get the link from another page to open the home page but scroll to the menu part of it. I don't even need it to smooth scroll or anything, just go to that spot. It looks like it does go there for like, one frame, as it's loading, but it keeps jumping to the top. It's simply beyond me to try and figure out what is causing it to lose this basic HTML (afaik) functionality and keep forcing me to the top of the page...
Any help would be really great, as I'm a bit of a noob when it comes to anything other than html/css and simple jquery.
Just append the anchor to the end of the link.
Simply insert a link like:
Link to section on another page
Edit: Just noticed you're not getting this to work. What do your links look like, and what's the HTML with the ID on the target page?
Try this jQuery code:
$(document).ready(function() {
function hashScroll() {
// get URL Hash
var hash = window.location.hash;
// check if hash is set and not empty
if (hash != '') {
// scroll to hash ID after 10ms delay
setTimeout(function() {
$(document).scrollTop( $(hash).offset().top );
}, 10);
// debugging
console.log(hash);
console.log('offset:'+ $(hash).offset().top );
}
}
hashScroll(); // fire hash scroll function
});
Explanation:
This function will capture the URL hash (www.example.com/#hash), checks if it's not empty and then scrolls the page to the element with the ID which matches the hash after 10 ms. The delay is there to make sure browsers don't mess up the loading process.

Keeping the page vertically fixed on an element, when lots of content is revealed above (so causing scroll)

I have a long page with lots of data tables of hidden content.
They are hidden as they are quite repetitive so not all users want to have to scroll past them all the time.
Frequently down the page there is the option to click to open up all of the hidden data tables.
The problem is, if you go half way down the page and click to open up the tables, all of the content being revealed above the current view causes the page to scroll down, meaning the user becomes disorientated as to where they are on the page.
I've mocked up the problem here. If you scroll down to one of the "show more" links nearer the bottom of the page you'll see what i mean.
http://jsfiddle.net/LnubwdzL/
I want the clicked link to remain static under the cursor so that the user knows where they are.
This kind of a solution:
$("a").on('click', function() {
$('html, body').animate({
scrollTop: $(this).offset().top
}, 2000);
});
... from other questions on SO, doesn't seem to cut it. Even if it ends up in the right place the page still moves about a lot before coming to rest.
If I understand it correctly and as I mentioned in comments, I think you can set the same duration value to both your slideDown(); and your animate() functions, and have them both inside the same click handler.
Your code may then become:
$('a').on('click', function(e){
e.preventDefault();
if($('.hide').length>0){$('html, body').animate({scrollTop:$(this).offset().top},400);}
$('.hide').hide().removeClass('hide').slideDown(400);
});
Hope this helps.
Update #1: Added a check on top of animate() so it does not animate when there is no $('.hide') element present anymore.
Update #2:
Take a look at this resulting fiddle of another experiment. Let me know if this was what you were looking for.
The way this works is:
Upon click of an anchor, offset().top of clicked element is first
stored in a variable named prevOffset.
Current $(window).scrollTop() value is also stored in a variable named
scrollTop.
Then all the .hide elements are temporarily made visible via $('.hide').show();.
Another offset().top of the same clicked element is then stored in a variable named currOffset.
All the .hide elements are made invisible again via $('.hide').hide();.
scrollTop is then animated to a value calculated as: scrollTop+(currOffset-prevOffset).
All $('.hide') elements are animated via slideDown().
JavaScript:
var duration=400,hideElements=null,scrollTop=0,prevOffset=0,currOffset=0;
$('a').on('click',function(e){
e.preventDefault();
hideElements=$('.hide');
if(hideElements.length>0){
scrollTop=$(window).scrollTop();
prevOffset=$(this).offset().top;
hideElements.show();
currOffset=$(this).offset().top;
hideElements.hide();
$('html, body').animate({scrollTop:scrollTop+(currOffset-prevOffset)},duration);
hideElements.removeClass('hide').slideDown(duration);
}
});
Hope this is what you were looking for.

Only remove jQuery slide transition from first instance of function?

Alright, I'm using the UberMenu Plugin for Wordpress. When you click the parent item in a menu, the child-menu slides down into position underneath and stays put. After clicking on a child-menu link, the normal function is for the child-menu to disappear and be reactivated by click on the parent item again.
So, I wanted the child-menu to stay visible after going to a child-page and afterwards continue with the original functionality after that very first instance. Miraculously, I've gotten this far with success.
You can view the working menu/sub-menu here: http://goo.gl/MC8Aw
I added this code to the UberMenu.dev.js:
jQuery('document').ready( function($){
var id = $( '#megaMenu ul.megaMenu > li.current-menu-item, #megaMenu ul.megaMenu > li.current-menu-parent, #megaMenu ul.megaMenu > li.current-menu-ancestor' ).live().first().attr( 'id' );
uberMenu_openMega( '#' + id );
});
You can see the entire .js file here: http://goo.gl/xZd6g
Alright, so the only issue is that when the child-page loads and the child-menu is triggered immediately by the above code, it's retaining the slide transition from the primary functionality. This gives a delayed look/experience to the child-menu that I want to avoid/minimize.
Is it possible to amend the above code (which seems already set up to only affect the first appearance of the menu) so that it also ignores the slide transition needed throughout the rest of the plugin?

On hover open a DIV, DIV content should dynamically load from a separate URL

I'm sure someone has already done this and posted it online, but I'm having trouble finding such an example or tutorial.
Basically, I want to have a series of links on the page. If you hover your mouse on the link, it should open a drop down DIV box under the link and then load content into the DIV from a remote URL that is pre-defined.
Has anyone seen such an implementation or have any ideas on how to do it with jQuery?
I think you're looking for something similar to:
$(document).ready(function(){
$("a").hover(function(){ //When a given link (<a> tag) is hovered over
$("div").load(this.href).show(); //load the src of that tag into a given div container.
});
});
Here's a simple test in jsFiddle, but I didn't know what to put with the href...so all you'll see is the div appear with the post error...not very pretty, but if anyone has suggestions then I'm definitely open to all.
http://jsfiddle.net/ChaseWest/VEuH9/2/
I would go with something like the following. Note that we target only anchors who don't have the loaded class. The reason why is because we don't want to load the contents for any anchor multiple times. Whenever the user passes over an anchor, its content will be loaded and it will get a special class indicated this. If they pass over it again, nothing happens.
$("body").on("mouseenter", "a:not(.loaded)", function(e){
$(".mydiv").load(e.target.href, function(){
$(e.target).addClass("loaded");
});
});

Categories