2013-09-09 3 views
25

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

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

<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, но я уверен.

+0

Мне нужен был способ пересчитать значение на странице resize и также добавьте держатель для пространства, чтобы наложение выполнялось гладко, например никакая страница не прыгает при прикреплении содержимого. Решение -> https://stackoverflow.com/a/47429990/996010 –

ответ

38

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

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

Работа демо: http://bootply.com/69848

В некоторых случаях offset.bottom также должны быть рассчитаны, чтобы определить, когда «не-аффикс» элемент. Here's an example of affix-bottom

+1

Ссылка не работает .. – 5ervant

+2

используйте .outerHeight() вместо .hight(), чтобы включить границу и дополнение – Armando

17

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

Вот аффикс на нем лучше.

Нормальный аффикс 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 
    }) 
}) 

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

+2

, вы мой герой! Спасибо человеку. PS другим: при использовании этого кода не забудьте добавить атрибут «data-smart-affix» в ваш аффикс-элемент. ;) – Mike

+1

Лучший ответ! хорошо сделано. это помогло мне исправить мою проблему. –

+0

В вашем коде есть ошибка, используйте «$ (this) .data (« bs.affix »). options.offset.top« вместо «$ (this) .data (' bs.affix '). options.offset». Также я могу предложить использовать [data-offset-top-dynamic вместо [data-smart-affix] –

1

Предлагаю вам добавить обертку вокруг прикрепленного 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/

0

Скелли выше прав и нет лучшего способа сделать это. Единственное возможное решение с «родным» бутстрапом - это привязать параметры аффикса с помощью JavaScript-вызова (как упоминалось выше в https://stackoverflow.com/a/18702972/2546679).

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

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

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

но один не разрешено писать, например:

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

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

+0

. Ваш ответ не динамический, а просто статический. – bigmike7801

+0

Да - это не автономный ответ, а дополнение к ответу Скелли (где мне не разрешают прокомментировать). Я просто попытался пояснить, что бессмысленно пытаться выразить динамическое вычисление аффикса без использования пользовательского JavaScript на странице - то, что я пробовал в течение нескольких часов, включая отладку подпрограмм bootstrap и JQuery. – haui

3

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

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

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

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

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

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

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

GI

0

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

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

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

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

0

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