问题
I'm using JQuery UI to make tabs in my application. I needed the tabs to be linkable (direct link that opens the page and selects the correct tab). This is done by using a hash tag/fragmented identifier. But I have a issue when the content above the tabs and inside the tabs is very long.
When clicking the tabs, the page scrolls down to the start of the tab. This is not what I want.
I'm using Jquery 1.7.1 and Jquery UI 1.8.16.
The javascript/Jquery code is a standard Jquery UI tabs with the addition to the event "tabsshow". This is suggested in Changing location.hash with jquery ui tabs (Stackoverflow question) and JQuery UI Tabs: Updating URL with hash while clicking the tab (blog - Tech Diary by Robin)
$(document).ready(function() {
$("#tabs").tabs();
/**
* Add hash to URL of the current page
*
* http://chwang.blogspot.com/2010/02/jquery-ui-tabs-updating-url-with-hash.html
* https://stackoverflow.com/questions/570276/changing-location-hash-with-jquery-ui-tabs
*/
$("#tabs").bind('tabsshow',function(event, ui) {
window.location.hash = ui.tab.hash;
});
});
The following HTML can be used to test the behavior
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js" type="text/javascript"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.16/jquery-ui.min.js" type="text/javascript"></script>
<div style="height: 400px;">Some other content</div>
<div id="tabs" class="ui-tabs ui-widget ui-widget-content ui-corner-all">
<ul class="ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all">
<li class="ui-state-default ui-corner-top"><a href="#tab_1"><span>Tab 1</span></a></li>
<li class="ui-state-default ui-corner-top"><a href="#tab_100"><span>Tab 100</span></a></li>
<li class="ui-state-default ui-corner-top ui-tabs-selected ui-state-active"><a href="#tab_1000"><span>Tab 1000</span></a></li>
</ul>
<div id="tab_1" class="ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide">
<table style="height: 1000px"><tr><td>Hello. This is tab 1</td></tr></table>
</div>
<div id="tab_100" class="ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide">
<table style="height: 1000px"><tr><td>Hello. This is tab 100.</td></tr></table>
</div>
<div id="tab_1000" class="ui-tabs-panel ui-widget-content ui-corner-bottom"><h2>Heading</h2>
<table style="height: 1000px"><tr><td>Hello. This is tab 1000.</td></tr></table>
</div>
</div>
When opening the page with the following URL, one should have tab 1 opened and not scroll down to where the tab starts. The same goes for clicking on one of the tabs.
file.html#tab_1
回答1:
This may not be the best method, but if you rename all of the ID's after the tabs have been created, then adding a hash with the original ID won't scroll the page. I used this method because even with javascript disabled, the hash will take the user to the correct ID. Here is a demo of the code below:
$("#tabs").tabs({
create: function(event, ui) {
// get tab plugin data
var tabs = $('#tabs').data('tabs'),
// tabs.anchors contains all of the tab anchors
links = tabs.anchors;
// tabs.panels contains each tab
tabs.panels.each(function(i){
// just adding a "mod_" prefix to every ID/hash
this.id = 'mod_' + this.id;
links[i].hash = '#' + this.id;
});
}
});
/**
* Add hash to URL of the current page
*
* http://chwang.blogspot.com/2010/02/jquery-ui-tabs-updating-url-with-hash.html
* http://stackoverflow.com/questions/570276/changing-location-hash-with-jquery-ui-tabs
*/
$("#tabs").bind('tabsshow', function(event, ui) {
// remove the prefix from the ID, so we're showing the original ID in the hash
window.location.hash = ui.tab.hash.replace('mod_', '');
});
回答2:
I'm using jQuery 1.11.1. This workes nicely for me.
$("#tabs").tabs(); //initialize tabs
$(function() {
$("#tabs").tabs({
activate: function(event, ui) {
var scrollTop = $(window).scrollTop(); // save current scroll position
window.location.hash = ui.newPanel.attr('id'); // add hash to url
$(window).scrollTop(scrollTop); // keep scroll at current position
}
});
});
jQuery UI tabs, update url when clicking on a different tab
Thanks to Jeff B for pointing me here http://jsfiddle.net/jtbowden/ZsUBz/44/
回答3:
As others have mentioned the code from @Mottie might have once worked on older versions of jQuery UI, but this has definitely stopped working. The jQuery UI Tabs api has changed quite a bit since that was written so here is an updated version that works with at least jQuery 1.10.2
Demo here: http://jsfiddle.net/xsx5u5g2/
var $tabs = $("#tabs");
$tabs.tabs({
create: function(event, ui) {
// Adjust hashes to not affect URL when clicked.
var widget = $tabs.data("uiTabs");
widget.panels.each(function(i){
this.id = "uiTab_" + this.id; // Prepend a custom string to tab id.
widget.anchors[i].hash = "#" + this.id;
$(widget.tabs[i]).attr("aria-controls", this.id);
});
},
activate: function(event, ui) {
// Add the original "clean" tab id to the URL hash.
window.location.hash = ui.newPanel.attr("id").replace("uiTab_", "");
},
});
回答4:
You have to change the window hash without scrolling the page. Here is already a question on SO - Modifying document.location.hash without page scrolling.
The changes required are:
$("#tabs").bind('tabsshow',function(event, ui) {
setHashWithoutScroll(ui.tab.hash);
});
The setHashWithoutScroll
function can be taken from the above mentioned link.
function setHashWithoutScroll(hash) {
hash = hash.replace( /^#/, '' );
var fx, node = $( '#' + hash );
if ( node.length ) {
node.attr( 'id', '' );
fx = $( '<div></div>' )
.css({
position:'absolute',
visibility:'hidden',
top: $(document).scrollTop() + 'px'
})
.attr( 'id', hash )
.appendTo( document.body );
}
document.location.hash = hash;
if ( node.length ) {
fx.remove();
node.attr( 'id', hash );
}
}
The accepted answer throws an error to me - jQuery UI Tabs: Mismatching fragment identifier
. So I had to use this one.
回答5:
I just added the following to my javascript:
$('#tabs').tabs();
// Direct links to the tabs, e.g. /my-page#tab-id can cause browsers
// to scroll down to half-way down the page, which is ugly. We override that here.
// (This can cause a brief FOUC effect where the page first displays then scrolls up)
window.scrollTop = '0';
window.scrollTo(0,0);
In MSIE, I get a brief FOUC effect as the page loads scrolled part-way-down, then flicks to the top.
In Firefox, this works fine without any visible FOUC.
In Chrome, this doesn't work at all -- see scrollTop does not work in Chrome, nor do suggested workarounds
回答6:
This simple method worked for me:
/* Prevent scroll to tab on click */
$(document).ready(function(){
$("a.ui-tabs-anchor").click(function(e){
e.preventDefault();
return false;
});
});
回答7:
I tried @mottie solution but is not working now (2 years after).
It triggers an error: TypeError: tabs is undefined
.
Following is an acceptable solution for me:
// preventing scroll
// $("#tabs li a[href^='#tab']").bind('click',function(e){ // less general but better
$("#tabs li a").bind('click',function(e){
$("html, body").animate({ scrollTop: 0 });
});
回答8:
There are many answers on this page, and in my mind, most are overcomplicating a simple issue.
Basically, the solution from david-thomas is the simplest and most effective. Essentially, all you want to be doing is preventing the default link behaviour on a tab link (<a>
tag).
The same answer applies to the bootstrap tabs, where you have to specify the click handler
$('.nav-tabs a').click(function(e){
e.preventDefault();
$(this).tab('show');
});
来源:https://stackoverflow.com/questions/8624531/preventing-scroll-when-using-uri-hash-to-identify-tab