JQuery UI Tabs Causing Screen to "Jump" - javascript

I'm using the latest version of the jQuery UI tabs. I have tabs positioned toward the bottom of the page.
Every time I click a tab, the screen jumps toward the top.
How can I prevent this from happening?
Please see this example:
http://5bosses.com/examples/tabs/sample_tabs.html

If you're animating your tab transitions (ie. .tabs({ fx: { opacity: 'toggle' } });), then here's what's happening:
In most cases, the jumping isn't caused by the browser following the '#' link. The page jumps because at the midpoint of the animation between the two tab panes, both tab panes are fully transparent and hidden (as in display: none), so the effective height of the whole tabbed section becomes momentarily zero.
And if a zero-height tabbed section causes the page to be shorter, then the page will appear to jump up to compensate, when in reality it's simply resizing to fit the (momentarily) shorter content. Makes sense?
The best way to fix this is to set a fixed height for the tabbed section. If this is undesirable (because your tab content varies in height), then use this instead:
jQuery('#tabs').tabs({
fx: { opacity: 'toggle' },
select: function(event, ui) {
jQuery(this).css('height', jQuery(this).height());
jQuery(this).css('overflow', 'hidden');
},
show: function(event, ui) {
jQuery(this).css('height', 'auto');
jQuery(this).css('overflow', 'visible');
}
});
It will set the computed height of the pane before the tab transition. Once the new tab has appeared, the height is set back to 'auto'. Overflow is set to 'hidden' to prevent content from breaking out of the pane when going from a short tab to a taller one.
This is what worked for me. Hope this helps.

If you have something along these lines:
Tab 1
Try adding return false; after the tab activation command:
Tab 1

My guess is that you are animating your tab transitions? I am having the same problem, where the page scroll jumps back to the top with every click.
I found this in the jquery source:
// Show a tab, animation prevents browser scrolling to fragment,
Sure enough, if I have this:
$('.tab_container > ul').tabs();
$('.tab_container > ul').tabs({ fx: { height: 'toggle', opacity: 'toggle', duration: 'fast' } });
my code jumps to the top and is annoying (but there's animation). If I change that to this:
$('.tab_container > ul').tabs();
//$('.tab_container > ul').tabs({ fx: { height: 'toggle', opacity: 'toggle', duration: 'fast' } });
there is no tab animation, but switching between tabs is smooth.
I found a way to make it scroll back, but it's not a proper fix, as the browser still jumps to the top after clicking a tab. The scroll happens between the events tabsselect and tabsshow, so the following code jumps back to your tab:
var scroll_to_x = 0;
var scroll_to_y = 0;
$('.ui-tabs-nav').bind('tabsselect', function(event, ui) {
scroll_to_x = window.pageXOffset;
scroll_to_y = window.pageYOffset;
});
$('.ui-tabs-nav').bind('tabsshow', function(event, ui) {
window.scroll(scroll_to_x, scroll_to_y);
});
I'll post any more progress I make.

I was given a solution for this...
How to stop screen from jumping up when tab is clicked:
Wrap the div that contains the tabs in a div with a fixed height.
See example here: http://5bosses.com/examples/tabs/sample_tabs.html

I had the same problem with jquery ui's menu - a preventDefault() on the anchor's click event stops the page from scrolling back to the top:
$("ul.ui-menu li a").click(function(e) {
e.preventDefault();
});

Mike's solution demonstrated the principle greatly but it has a big drawback - if the resultant page is short, the screen will jump to the top anyway! The only solution is to remember the scrollTop, and restore it after the tabs are switched. But before the restoration, enlarge the page (html tag) appropriatelly:
(edit - modified for new Jquery UI API + small improvement for large pages)
$(...).tabs({
beforeActivate: function(event, ui) {
$(this).data('scrollTop', $(window).scrollTop()); // save scrolltop
},
activate: function(event, ui) {
if (!$(this).data('scrollTop')) { // there was no scrolltop before
jQuery('html').css('height', 'auto'); // reset back to auto...
// this may not work on page where originally
// the html tag was of a fixed height...
return;
}
//console.log('activate: scrolltop pred = ' + $(this).data('scrollTop') + ', nyni = ' + $(window).scrollTop());
if ($(window).scrollTop() == $(this).data('scrollTop')) // the scrolltop was not moved
return; // nothing to be done
// scrolltop moved - we need to fix it
var min_height = $(this).data('scrollTop') + $(window).height();
// minimum height the document must have to have that scrollTop
if ($('html').outerHeight() < min_height) { // just a test to be sure
// but this test should be always true
/* be sure to use $('html').height() instead of $(document).height()
because the document height is always >= window height!
Not what you want. And to handle potential html padding, be sure
to use outerHeight instead!
Now enlarge the html tag (unfortunatelly cannot set
$(document).height()) - we want to set min_height
as html's outerHeight:
*/
$('html').height(min_height -
($('html').outerHeight() - $('html').height()));
}
$(window).scrollTop($(this).data('scrollTop')); // finally, set it back
}
});
Works with the fx effect too.

Try using event.preventDefault();. On the click event which is switching the tabs. My function looks like this:
$(function() {
var $tabs = $('#measureTabs').tabs();
$(".btn-contiue").click(function (event) {
event.preventDefault();
$( "#measureTabs" ).tabs( "option", "active", $("#measureTabs").tabs ('option', 'active')+1 );
});
});

Thanks for your help. Good suggestion, but I tried before with no luck. I think JQuery UI may be overriding my efforts.
Here is the code per tab:
<li class=""><span>Two</span></li>
I already tried this with no success:
<li class=""><span>Two</span></li>
Here is a simple example (without return false): http://5bosses.com/examples/tabs/sample_tabs.html
Any other suggestions?

Try just adding a min-height using css to each of the tab content areas ( not the tabs themselves ). That fixed it for me. :)

> var scroll_to_x = 0; var scroll_to_y =
> 0;
> $('.ui-tabs-nav').bind('tabsselect',
> function(event, ui) {
> scroll_to_x = window.pageXOffset;
> scroll_to_y = window.pageYOffset; }); $('.ui-tabs-nav').bind('tabsshow',
> function(event, ui) {
> window.scroll(scroll_to_x, scroll_to_y); });
Thanks for your help! Please let me know what else you find.
The above function works (screen doesn't move permanently)... but, the screen is very wobbly on click.
Here is a simple example showing how clicking a tabs causes the screen to jump toward the top (without the above code):
http://5bosses.com/examples/tabs/sample_tabs.html
Note that there's no animation being used.

I prefer to have an href="#" in my links that do not take the user anywhere, but you can do this as long as you add an onclick="return false;". The key, I guess, is not sending the user to "#", which depending on the browser seems to default as the top of the current page.

There is a much more simple way which I discovered from the comments on this page that is to simply remove the href="#" and it will not jump to the top any more! I verified and it works for me. Cheers

I had such a problem. My code was:
$("#tabs").tabs({
hide: {
effect: "fade",
duration: "500"
},
show: {
effect: "fade",
duration: "500"
}
});
I have simply removed show and it worked like a charm!
$("#tabs").tabs({
hide: {
effect: "fade",
duration: "500"
}
});

I had the same problem, plus mine were rotating on their own so if you were at the bottom of the page, the browser window would be scrolled up tot he top. Having a fixed height for the tab container worked for me. Kind of a weird thing still is that if you leave the window or tab and go back, it will still scroll. Not the end of the world, though.

replace the href="#" with href="javascript:void(0);" in 'a' element
works 100%

I found in my case the tab href=#example1 was causing the page to jump to the position of the id. Adding a fixed height to the tabs made no difference so I just added:
$('.nav-tabs li a').click( function(e) {
e.preventDefault();
});

Did you tryed:
fx: {opacity:'toggle', duration:100}

Related

jQuery: set if else statement to perform offset based on browser width

Finishing up a parallax, one page site and I've got a fixed nav, so I have to offset the various div's / sections on my page so they don't get cut off on top. Problem is performing this for different browser widths, since my fixed nav will be about half the height on mobile as it is on desktop.
Trying this jQuery out and it only seems to perform the else action, not the if. So the offset is too much on mobile. Here's what I'm currently using:
<script type="text/javascript">
jQuery(document).ready(function() {
jQuery('.main-navigation a[href^="http://example.com/#"]' ).click(function() {
if (jQuery(window).width() < 677) {
jQuery.scrollTo( this.hash, 1000, { easing:'swing', offset:-20 });
} else {
jQuery.scrollTo( this.hash, 1000, { easing:'swing', offset:-141 });
}
});
});
</script>
I think this will provide a more responsive solution:
$(document).ready(function() {
$.resizeContentHeight = function(){
$('#main-content').css("margin-top", $(".header-fixed").height());
}
$(window).load(function() {
$.resizeContentHeight();
});
$(window).resize(function() {
$.resizeContentHeight();
});
});
In this JSfiddle I calculate the height of the .header-fixed and apply that as a margin-top to the content below it (#main-content). I think this is what you are trying to achieve right? I have tested this and modified it to work across multiple browsers. Not sure if this will be relevant in a parallax site if you could provide examples of the HTML you are working with it would help. This will also adjust if the user changes the orientation of their device.
This could also be adapted to add or remove the height of the header to the anchor links.

Change scrollTop offset

I am using bootstrap 3 and have a fullscreen hero unit at the top of my page, below that is my navigation. I have some js which allows my navbar to stick to be fixed at the top after you scroll past the full screen hero. Also some js for my smooth scrolling links.
The problem is the offset is different before you scroll past the full screen hero and after. But it works fine when you are past the jumbotron. I have tried a bunch of different things but I can seem to get this to work exactly.
Check out the fiddle here.
Here is my js for the smooth scrolling links:
$(document).ready(function() {
// navigation click actions
$('.scroll-link').on('click', function(event){
event.preventDefault();
var sectionID = $(this).attr("data-id");
scrollToID('#' + sectionID, 750);
});
// scroll to top action
$('.scroll-top').on('click', function(event) {
event.preventDefault();
$('html, body').animate({scrollTop:0}, 1200);
});
// mobile nav toggle
$('#nav-toggle').on('click', function (event) {
event.preventDefault();
$('#main-nav').toggleClass("open");
});
});
// scroll function
function scrollToID(id, speed){
var offSet = 95;
var targetOffset = $(id).offset().top - offSet;
var mainNav = $('#main-nav');
$('html,body').animate({scrollTop:targetOffset}, speed);
if (mainNav.hasClass("open")) {
mainNav.css("height", "1px").removeClass("in").addClass("collapse");
mainNav.removeClass("open");
}
}
if (typeof console === "undefined") {
console = {
log: function() { }
};
}
By changing var offSet = 95; I am able to adjust the offset but what would be the best way to use 180 before the navbar sticks to the top but 95 when it does?
Also here is the js I am using for my navbar:
$(function () {
/* $(".navbar-fixed-top").css({"top":$(".jumbotron").height()});
$(window).resize(function (e) {
$(".navbar-fixed-top").css({"top":$(".jumbotron").height()});
});*/
$(document).on( 'scroll', function(){
console.log('scroll top : ' + $(window).scrollTop());
if($(window).scrollTop()>=$(".jumbotron").height())
{
$(".navbar").addClass("navbar-fixed-top");
}
if($(window).scrollTop()<$(".jumbotron").height())
{
$(".navbar").removeClass("navbar-fixed-top");
}
});
});
Are you open to angular.js? I have a directive i use for this. As seen here.
I'll grab the plunker link for you. you might find the code helpful.
Essentially you need to create a ghost dom element to take the place of the menu when you pull it to an new layout position.
EDIT: Here it is
I won't suggest grabbing angular just for this. But you can use the basis of the events and logic to build your own solution.
This here is creating an element and placing in its place
$scope.spacer = $element.after(
'<div class="spacer" style="height:' + $element[0].clientHeight + 'px"> </div>').next();
then this element is removed when the menu is back to its static position.
Inspect the dom and watch how it changes, this will probably help you see the events and changes that need to take place.
EDIT 2 SOLUTION:
HERE is the concepts applied to your JSFiddle
It's not the best solution but by adding margin: 0 0 -100px 0; to your .navbaryou lose the spacing issue.
Also you're getting 22 console errors because of missing images. I'm not saying that this is causing any major problems but you would be better off losing them.
The problem is that when you have not scrolled past the hero, navigation is still part of the layout and pushes content bellow it a little lower. When you scroll past (either manually or via a script) the hero, navigation is removed and fix positioned. That makes everything which was bellow to "jump up" exactly of the navigation height.
That means if portfolio was 1000px from the top, on click you say: go 1000px from top; but then porfolio moves 100px up (as explained above) meaning it is now 900px from the top while the window scrolled 1000px as you asked.
When you have scrolled past the hero, nothing changes its position.

Show an element at the bottom of the page with javascript

In a guestbook I have a button at the bottom of the page which displays the input form on click:
$("a#showform").click(function(){
$(this).hide();
$("div#post").show("slow");
});
The problem is that the appearing form is outside the current view port and only manual scrolling makes the form visible to the user. I couldn't find any solution from the web but this must be a very common issue. Isn't there a jquery command to "stick to bottom" or similar?
Next thing is: I use nanoScroller on the whole page, so normal downscrolling methods won't work here. nanoScroller has a method scroll:"bottom" but it isn't smooth...
Thank you very much,
Toni
You can easially scroll to the bottom of the page whenever your webpage expands :
$("a#showform").click(function(){
$(this).hide();
$("div#post").show("slow");
$('html, body').animate({
scrollTop:$(document).height()
}, 'slow');
});
you can set the 'slow' of the .animate() to any speed in miliseconds.
jsFiddle
Just ajust the scrolling within your function
$("a#showform").click(function(){
$(this).hide();
$("div#post").show("slow");
/* $(scroll magically to #post) */
$("div#post").nanoScroller({ scroll: 'top' });
});
You may wish to use css to solve this problem if you aren't concerned with the post item covering other elements:
div#post {
position: fixed;
bottom: 0px;
}

scroll automatically to target with jQuery in iOS running too far

I have an anchor that when click I have the following jQuery firing:
$(document).on('pageinit', function (event, ui) {
var page = $(event.target);
page.find('a.course_name').on('vclick', function() {
page.stop().animate({ scrollTop : $(this).offset().top }, 400);
}
}
What I am finding on the iPhone 5 running iOS 6 is that the animation of the scroll doesn't stop at the top of the anchor as I would like. It sometimes stops short, or runs past dependant on what I have scrolled to in the page previously.
I am also using jQuery Mobile, but essentially the page variable is the scrollable area.
I don't know your HTML markup or your CSS styles, but depending on it, position can return a different result than offset.
Try it with position() instead:
page.stop().animate({ scrollTop : $(this).position().top }, 400);

Navigation fade in after scroll down?

I would like to get a navigation exactly like this website : http://www.interviewmagazine.com/
A navigation bar appears after scrolling down about 700 pixels or so.. its a fixed nav with fade in effect and has a fade out effect when you scroll back to top.
I tried to see how they did their code but i couldnt figure it out.
sounds like mootools tho?
If someone can help that would be awesome. thanks!
You can create such a menu using jQuery and CSS, swapping classes as needed when:
var posit = window.scrollTop();
if (posit == [your designated fadein location]) {
//do something;
}
CSS: position : fixed, opacity : 0, height : 0; overflow : hidden
swap class to change height to fixed amount
animate({opacity : 1.0}, 'fast', function() {
//callback;
});
You'll have to set a listener for when user scrolls, but this should get you started. All you need is jQuery and a browser, a logical approach to cut the project up into manageable parts, and time.
EDIT: Here's your fiddle.
http://jsfiddle.net/lazerblade01/fNn7K/26/
For anyone searching through stackoverflow here is my try:
$(function(){
// Check the initial Poistion of Sticky Header
var stickyHeaderTop = $('#stickyheader').offset().top;
$(window).scroll(function(){
if( $(window).scrollTop() > stickyHeaderTop ) {
$('#stickyheader').css({position: 'fixed', top: '0px'});
$('#stickyheader').css('opacity', '1');
} else {
$('#stickyheader').css({position: 'static', top: '600px'});
$('#stickyheader').css('opacity', '0');
}
});
});
Here is a Fiddle DEMO http://jsfiddle.net/uFq2k/297/
It is a little modified version of this code: how can I stick the div after scrolling down a little
David Walsh has a thing he calls ScrollSpy - much like twitter's scroll spy - only it does a different thing.
the twitter one can react to a particular element of interest coming into view.
walsh's plugin can react and give you events when a user scrolls to a particular threshold and back.
http://davidwalsh.name/mootools-scrollspy
You could try Twitter's Bootstrap. Check out their second toolbar.

Categories

Resources