Подтвердить что ты не робот

Как получить динамические значения смещения данных для метода ассемблера Bootstrap 3

Я хотел бы использовать метод Affix, описанный в документации Bootstraps (http://getbootstrap.com/javascript/#affix), однако навигационная панель, которую я хотел бы установить на начало страницы после прокрутки к ней может иметь разные значения смещения в зависимости от содержимого над ним.

Вот пример навигатора:

<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>

Как вы можете видеть, data-offset-top в настоящее время установлен в 200. Это работает отлично, если содержание выше 200px высотой, но содержимое выше динамическое, и поэтому высота над этой навигационной панелью не всегда одинакова. Как я могу сделать vale для data-offset-top динамическим?

Я предполагаю, что мне нужно будет использовать способ javascript, но я уверен.

4b9b3361

Ответ 1

Вы можете использовать jQuery для получения высоты динамического содержимого над navbar. Например:

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

Рабочая демонстрация: http://bootply.com/69848

В некоторых случаях, offset.bottom также должен быть рассчитан, чтобы определить, когда "un-affix" элемент. Вот пример аффикс-дна

Ответ 2

Я был абсолютно расстроен тем, как это работает, каждый раз выполняя некоторые пользовательские вычисления и создавая смещение от высот элементов выше желаемого аффикса.

Здесь лучше всего прикрепите к нему.

Нормальный аффикс 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 = $(this).offset().top
  })
})

Я также разместил это на обзоре кода.

Ответ 3

Данные ThomasReggi-smart-affix не работали для меня в некоторых случаях (при изменении размера документа или когда столбец с надписью был слишком высоким). Но это дало мне простую идею: добавьте пустой элемент перед прикрепленным контентом и используйте его для получения смещения. Хорошо работает при изменении размера.

Пока я был на нем, я также устанавливал ширину элемента как естественную ширину в исходном родителе. Здесь мое решение:

$('[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 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);
});

HTML, который идет с ним:

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

или

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

Необходимый CSS:

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

Если вы хотите отключить аффикс (например, при выравнивании нужного столбца), используйте CSS:

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

внутри соответствующего медиа-запроса.

GI

Ответ 4

Я предлагаю вам добавить обертку вокруг прикрепленного div - чтобы избежать "прокрутки" с прикрепленным навигатором. Томас опубликовал хорошее решение, но он не содержит затухающего пространства после аффикса, и он не работает в версии 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();
   });

});

Здесь вы можете найти пример: http://jsfiddle.net/3ss7fk92/

Ответ 5

Скелли выше правильно, и нет лучшего способа сделать это. Единственное возможное решение с "родным" бутстрапом - это присоединение параметров аффикса с вызовом JavaScript (как упоминалось выше в fooobar.com/questions/218471/...).

В особенности не можно использовать атрибут data-offset для достижения такого же эффекта (даже если это было бы намного удобнее, и даже если документация для Affix at http://getbootstrap.com/2.3.2/javascript.html#affix повышает надежду, что можно это сделать).

Таким образом, можно написать

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

но один не разрешен для записи, например:

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

Причина в том, что атрибуты данных анализируются с помощью API JQuery .data(), который позволяет анализировать только чистые значения JSON, см. https://api.jquery.com/data/.

Ответ 6

Thnx ThomasReggi за идею. Но может быть правильнее написать:

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

для таких, как я, которым также нужно было нижнее значение, которое будет писать аналогично.

Кстати, я думаю, что оберните его в декораторе на основе setTimeout (несколько как debounce).

Ответ 7

У меня были проблемы с этим раньше, и по какой-то причине я не мог получить ни одно из решений, которые другие люди предлагали работать. Я относительно новичок в Bootstrap и JQuery, поэтому я, вероятно, делал что-то неуловимое, которого я не ловил. Независимо от того, я нашел решение, которое работает очень хорошо, хотя он строго использует функциональность аффикса, как предполагает Bootstrap. Я сохранил свой #thisElement.affix {top: desiredFixedPosition;} CSS неповрежденным, но избавился от атрибутов data-spy и data-offset-top от тега #thisElement HTML. Я тогда жестко закодировал это в 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);
}

Насколько я тестировал, это работает независимо от того, насколько сильно вы изменяете размер страницы или прокручиваете, и если вы сориентируетесь с тем, как вы называете ее в функции $(document).ready(), вы можете даже оставить меню в правильном порядке положение во время анимации высоты. Как уже было сказано, это технически не полностью "одобренное Bootstrap" решение, но оно достаточно хорошо интегрируется в сайт Bootstrap, что он должен работать для некоторых:)