使用URI哈希标识选项卡时如何防止滚动?

12
我正在使用JQuery UI来制作我的应用程序中的选项卡。 我需要选项卡可以链接(直接链接打开页面并选择正确的选项卡)。 这是通过使用散列标签/fragmented identifier完成的。 但是,当选项卡上方和内部的内容非常长时,我会遇到问题。
点击选项卡时,页面会向下滚动到选项卡的开始位置。这不是我想要的。
我正在使用Jquery 1.7.1和Jquery UI 1.8.16。
Javascript / Jquery代码是标准的Jquery UI选项卡,还添加了“tabsshow”事件。这建议在Changing location.hash with jquery ui tabs(Stackoverflow问题)和JQuery UI Tabs: Updating URL with hash while clicking the tab(博客 - 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://dev59.com/mnRB5IYBdhLWcg3wn4YL
     */
    $("#tabs").bind('tabsshow',function(event, ui) {
        window.location.hash = ui.tab.hash;
    });
});

以下 HTML 可用于测试行为。
<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>

打开以下URL时,应该打开选项卡1,并不要滚动到选项卡开始的位置。点击其中一个选项卡也是同样的情况。
file.html#tab_1

可能是JQuery UI Tabs Causing Screen to "Jump"的重复问题。 - Software Engineer
不是完全相同,但非常相似。 - HNygard
8个回答

5

像其他人提到的那样,@Mottie 的代码可能曾经适用于旧版本的 jQuery UI,但现在已经停止工作。自那时起,jQuery UI Tabs api 发生了相当大的变化,因此这里提供一个更新后的版本,可以至少与 jQuery 1.10.2 兼容。

演示在这里: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_", "");
  },
});

我对此进行了一项修改。我不希望在页面加载/创建时重命名ID。我希望它发生在用户第一次单击选项卡时。这确保了书签URL正常工作。我将ID重命名拆分为一个单独的函数,然后将其包装到“仅运行一次”的结构中,并将其添加为“激活”内部的第一行。http://davidwalsh.name/javascript-once - mastaBlasta

5
我正在使用jQuery 1.11.1。这对我非常有帮助。
$("#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标签页,在单击不同的选项卡时更新网址

感谢Jeff B将我引导到这里 http://jsfiddle.net/jtbowden/ZsUBz/44/


对我来说也完美地运作了。适用于jQuery版本1.12.4。谢谢! - DpEN

5

这可能不是最好的方法,但如果在标签创建后重命名所有ID,那么添加原始ID的哈希将不会滚动页面。 我之所以使用此方法,是因为即使禁用javascript,哈希也会将用户带到正确的ID。以下是代码示例

$("#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
 * https://dev59.com/mnRB5IYBdhLWcg3wn4YL
 */
$("#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_', '');
});

1

您需要在不滚动页面的情况下更改窗口哈希。这里已经有一个关于SO的问题 - 修改document.location.hash而不滚动页面

所需更改如下:

$("#tabs").bind('tabsshow',function(event, ui) {
    setHashWithoutScroll(ui.tab.hash);
});

可以从上述链接中获取setHashWithoutScroll函数。

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 );
    }
}

被接受的答案对我来说会抛出一个错误 - jQuery UI Tabs: Mismatching fragment identifier。所以我不得不使用这个。


这并不能解决带有“#tab-id”的入站链接,加载页面时滚动部分的问题。 - Rich

0

这个简单的方法对我很有效:

/* Prevent scroll to tab on click */
$(document).ready(function(){
  $("a.ui-tabs-anchor").click(function(e){
      e.preventDefault();
      return false;
  });
});

0
我刚刚在我的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);

在MSIE中,当页面加载滚动部分时,我会看到一个短暂的FOUC效果,然后突然跳到顶部。
在Firefox中,这个功能完全没有任何可见的FOUC。
在Chrome中,这根本不起作用--请参见scrollTop在Chrome中不起作用,建议的解决方法也不起作用

-1

这个页面上有很多答案,但在我看来,大多数都过于复杂化了一个简单的问题。

基本上,david-thomas 的解决方案是最简单和最有效的。实质上,你要做的就是防止标签链接(<a> 标签)的默认行为。

同样的答案也适用于 Bootstrap 标签页,其中你必须指定点击处理程序。

   $('.nav-tabs a').click(function(e){
        e.preventDefault();
        $(this).tab('show');
    });

感谢您的深入和有益的评论。对于我回答导致您的应用程序从高处跌落,我深感抱歉... - JackDev

-1

我尝试了@mottie的解决方案,但现在(两年后)不起作用。
它会触发一个错误:TypeError:tabs未定义

以下是我可以接受的解决方案:

// 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 });
});

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接