jQuery 如何获取 Bootstrap 3 词缀方法的动态数据偏移值

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18702376/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-26 22:16:20  来源:igfitidea点击:

How to get dynamic data-offset values for Bootstrap 3 affix method

jquerycsstwitter-bootstraptwitter-bootstrap-3affix

提问by bigmike7801

I would like to use the Affix method described in Bootstraps documentation (http://getbootstrap.com/javascript/#affix), however the navbar I would like to fix to the top of the page after it scrolls to it can have different offset values depending upon the content above it.

我想使用 Bootstraps 文档(http://getbootstrap.com/javascript/#affix)中描述的 Affix 方法,但是我想在滚动到页面后修复到页面顶部的导航栏可以有不同的偏移值取决于它上面的内容。

Here's an example of the navbar:

这是导航栏的示例:

<div class="navbar navbar-default" data-spy="affix" data-offset-top="200">
  <ul class="nav navbar-nav">
    <li class="active"><a href="#">Link</a></li>
    <li><a href="#">Link 1</a></li>
    <li><a href="#">Link 2</a></li>
  </ul>
</div>

As you can see, the data-offset-topis currently set at 200. This works fine if the content above is 200px tall, but the content above is dynamic and so the height above this navbar isn't always the same. How can I make the vale for data-offset-topbe dynamic?

如您所见,data-offset-top当前设置为 200。如果上面的内容高度为 200 像素,这可以正常工作,但上面的内容是动态的,因此导航栏上方的高度并不总是相同。我怎样才能使 valdata-offset-top成为动态的?

I'm guessing I'll have to use the javascript way of doing it but I'm nit sure.

我猜我将不得不使用 javascript 的方式来做这件事,但我不确定。

回答by Zim

You could use jQuery to get the dynamic content height above the navbar. For example:

您可以使用 jQuery 获取navbar. 例如:

$('#nav').affix({
      offset: {
        top: $('header').height()
      }
}); 

Working demo: http://bootply.com/69848

工作演示:http: //bootply.com/69848

In some cases, offset.bottom must also be calculated to determine when to "un-affix" the element. Here's an example of affix-bottom

在某些情况下,还必须计算 offset.bottom 以确定何时“取消附加”元素。这是一个词缀底部的例子

回答by ThomasReggi

I was absolutely frustrated with the way this works, every time doing some custom calculation and building the offset off the the heights of the elements above the desired affix.

我对这种工作方式感到非常沮丧,每次都进行一些自定义计算并根据所需词缀上方的元素高度构建偏移量。

Here's affix at it's best.

这是最好的词缀。

The normal boostrap affix doesn't take the items natural offset top position into account, you have to manually pass it in as an attribute. This takes care of that, and accounts for the offset top changing on window resize.

正常的 boostrap 词缀不考虑项目的自然偏移顶部位置,您必须手动将其作为属性传入。这会解决这个问题,并考虑到窗口调整大小时偏移顶部的变化。

var $attribute = $('[data-smart-affix]');
$attribute.each(function(){
  $(this).affix({
    offset: {
      top: $(this).offset().top,
    }
  })
})
$(window).on("resize", function(){
  $attribute.each(function(){
    $(this).data('bs.affix').options.offset.top = $(this).offset().top
  })
})

I also posted this on code review.

我也在代码上发布了这个。

Don't forget to add the data-smart-affixattribute to your affix element

不要忘记将data-smart-affix属性添加到您的词缀元素

Try this sample code: https://jsfiddle.net/NabiKAZ/qyrauogw/
(In this sample, the height of red section may be 100px or 200px or 300px in diffrence width of window, So need to diffrence data-offset-topwhen scrolled.)

试试这个示例代码:https: //jsfiddle.net/NabiKAZ/qyrauogw/
(在这个示例中,红色部分的高度在窗口的差异宽度上可能是100px或200px或300px,因此data-offset-top滚动时需要差异。)

回答by gi1242

ThomasReggi's data-smart-affix didn't work for me in some corner cases (when resizing the document, or when the affixed column was too tall). But it gave me a simple idea: Add an empty element before the affixed content, and use that to get the offset. Works well when resized.

在某些极端情况下(调整文档大小或附加列太高时),ThomasReggi 的 data-smart-affix 对我不起作用。但它给了我一个简单的想法:在附加内容之前添加一个空元素,并使用它来获取偏移量。调整大小时效果很好。

While I was at it, I also set the width of the element to be it's natural width in the original parent. Here's my solution:

当我在做的时候,我还将元素的宽度设置为原始父元素的自然宽度。这是我的解决方案:

$('[data-affix-after]').each( function() {
  var elem = $(this);
  var parent_panel = elem.parent();
  var prev = $( elem.data('affix-after') );

  if( prev.length != 1 ) {
    /* Create a new element immediately before. */
    prev = elem.before( '<div></div>' ).prev();
  }

  var resizeFn = function() {
      /* Set the width to it's natural width in the parent. */
      var sideBarNavWidth = parent_panel.width()
          - parseInt(elem.css('paddingLeft'))
          - parseInt(elem.css('paddingRight'))
          - parseInt(elem.css('marginLeft'))
          - parseInt(elem.css('marginRight'))
          - parseInt(elem.css('borderLeftWidth'))
          - parseInt(elem.css('borderRightWidth'));
      elem.css('width', sideBarNavWidth);

      elem.affix({
          offset: {
              top: prev.offset().top + prev.outerHeight(true),
              bottom: $('body>footer').outerHeight(true)
          }
      });
  };

  resizeFn();
  $(window).resize(resizeFn);
});

The HTML that goes with it is:

与之配套的 HTML 是:

<div id='before-affix'></div><!-- leave this empty -->
<div data-affix-after='#before-affix'>
    Put content to affix here.
</div>

or

或者

<div data-affix-after='#create'><!-- any ID that doesn't exist -->
    Put content to affix here.
</div>

The required CSS is:

所需的 CSS 是:

.affix { top: 0px },
.affix-bottom { position: absolute; }

If you want to disable affix (e.g. when the right column is stacked), then use the CSS:

如果您想禁用词缀(例如,当右列堆叠时),请使用 CSS:

.affix, .affix-bottom { position: static; }

inside the appropriate media query.

在适当的媒体查询中。

GI

胃肠道

回答by pixelofficer

I suggest you to add wrapper around affixed div - to avoid the "scroll jump" with affixed navbar. Thomas posted nice solution, but it doesn't include colapsed space after affix and it's not working in 2.x boostrap version which I must use. So i decided to write completly new implementation of affix. It doesn't need boostrap, just jquery. It's my first javascript, so please have mercy :) but maybe it will help somebody. It's always nice to have solution without a bootstrap

我建议您在附加的 div 周围添加包装器 - 以避免带有附加导航栏的“滚动跳转”。Thomas 发布了不错的解决方案,但它不包含词缀后的折叠空间,并且它在我必须使用的 2.x boostrap 版本中不起作用。所以我决定写一个全新的词缀实现。它不需要boostrap,只需要jquery。这是我的第一个 javascript,所以请怜悯:) 但也许它会帮助某人。没有引导程序的解决方案总是很好

function myaffix() {

var affixoffset = $('.navbar').offset().top

$('#nav-wrapper').height($(".navbar").height());

$(window).scroll(function () {

    if ($(window).scrollTop() <= affixoffset) {
        $('.navbar').removeClass('affix');
    } else {
        $('.navbar').addClass('affix');
    }
});

};

$(document).ready(function () {

   myaffix();

   $(window).on("resize", function () {
       myaffix();
   });

});

You can find example here: http://jsfiddle.net/3ss7fk92/

你可以在这里找到例子:http: //jsfiddle.net/3ss7fk92/

回答by haui

Skelly above is right and there is no better way to do so. The only possible solution with "native" bootstrap is to attach the affix options with a JavaScript call (as mentioned above in https://stackoverflow.com/a/18702972/2546679).

上面的斯凯利是对的,没有更好的方法来做到这一点。“本机”引导程序的唯一可能解决方案是通过 JavaScript 调用附加词缀选项(如上文https://stackoverflow.com/a/18702972/2546679 中所述)。

It is especially notpossible to use the data-offsetattribute to achieve the same effect (even if this would be much more convenient, and even if the documentation for Affix at http://getbootstrap.com/2.3.2/javascript.html#affixraises hope one could do so).

这是特别能够使用的data-offset属性来达到同样的效果(即使这将是方便多了,而且即使在文档词缀http://getbootstrap.com/2.3.2/javascript.html#affix加薪希望有人可以这样做)。

So one can write

所以一个人可以写

data-offset='{"top":42}'

but one is notallowed to write e.g.:

但一个允许写例如:

data-offset='{"top":$("#banner").height()}'

The reason is that the data attributes are parsed through the JQuery .data()API which only allows pure JSON values to be parsed, see https://api.jquery.com/data/.

原因是数据属性是通过 JQuery .data()API解析的,JQuery API 只允许解析纯 JSON 值,请参见https://api.jquery.com/data/

回答by discodanser

Thnx ThomasReggi for an idea. But may be more correct to write:

谢谢 ThomasReggi 的想法。但可能更正确的写法是:

$(this).data('bs.affix').options.offset.top = $(this).offset().top

for those like me who needed a bottom value too that would write analogically.

对于像我这样需要一个底部值的人来说,可以类比地写。

BTW also I think wrap it in a decorator based on setTimeout (somewhat like debounce).

顺便说一句,我也认为将它包装在一个基于 setTimeout 的装饰器中(有点像 debounce)。

回答by Patrick Menard

I was having a lot of trouble with this earlier, and for some reason I couldn't get any of the solutions other people had suggested to work. I'm relatively new to Bootstrap and JQuery, so I was probably doing something wonky I wasn't catching. Regardless, I found a solution that works really well, although it doesn't strictly speaking use the affix functionality as Bootstrap intends. I kept my #thisElement.affix {top: desiredFixedPosition;}CSS intact, but got rid of the data-spyand data-offset-topattributes from #thisElement's HTML tag. I then hard-coded this in JQuery:

早些时候我遇到了很多麻烦,出于某种原因,我无法获得其他人建议的任何解决方案。我对 Bootstrap 和 JQuery 比较陌生,所以我可能在做一些我没有注意到的奇怪的事情。无论如何,我找到了一个非常有效的解决方案,尽管严格来说它并没有像 Bootstrap 那样使用词缀功能。我保持我的#thisElement.affix {top: desiredFixedPosition;}CSS 完好无损,但是去掉了#thisElement 的 HTML 标签中的data-spydata-offset-top属性。然后我在 JQuery 中对此进行了硬编码:

var newAffix = function() {
    if($("otherElementsAboveThisElement").height() <= $(window).scrollTop()) {
        $("#thisElement").addClass("affix");
    } else {
        $("#thisElement").removeClass("affix");
    }
}

$(document).ready(function() {
    $(window).resize(newAffix);
    $(window).scroll(newAffix);
}

As far as I've tested, this works regardless of how much you resize the page or scroll, and if you get creative with how you call it in the $(document).ready()function you could even have the menu remain in the right position during height animations. As stated, this isn't technically a fully "Bootstrap approved" solution, but it integrates well enough into a Bootstrap site that it should work for some :)

据我测试,无论您调整页面大小或滚动多少,这都有效,如果您对在$(document).ready()函数中调用它的方式有创意,您甚至可以在高度动画期间将菜单保持在正确的位置。如上所述,这在技术上不是一个完全“Bootstrap 批准”的解决方案,但它很好地集成到 Bootstrap 站点中,它应该适用于某些 :)