Здравствуйте!
Есть в начале статьи статичное оглавление. Нужно сделать, чтобы при скроле статьи к top: 0px закреплялась небольшая position: fixed плашка height: 56px, внутри которой будет название пункта, который сейчас просматривается. При клике на эту небольшую плашку раскрываются все пункты оглавления.
Я это реализовал, но не уверен в чистоте и оптимизации кода. Может кто-то посоветует, как можно сделать лучше. Спасибо.
Получился следующий код:
var
toc_height = $('nav.toc').height() + $('nav.toc').offset().top, // нижняя точка статичного оглавления
topic_top[], //массив, в котором расположение (offset().top) каждого заголовка
topic_text = [], //массив, в котором расположен текст заголовков
topic_select = $('div.article *[id]'), //выбираю все элементы в теле статьи с ID (в моем случае = все заголовки)
topic_count = topic_select.length, //считаю количество заголовков
justExecuted = false; //из интернета для оптимизации количества операция при скролле
for (var i = 0; i < topic_count; i++) {
topic_top[i] = Math.floor(topic_select.eq(i).offset().top); //сохраняю в массив расположение заголовков
topic_text = topic_select.eq(i).text(); //сохраняю текст заголовков
}
topic_top[i] = 20000; // конец страницы
$(window).scroll(function() {
if(justExecuted) {return;} //из интернета для оптимизации количества операция при скролле
var current_scroll = $(window).scrollTop(); // сохраняю текущую позицию скролла
if (current_scroll > toc_height) { // если текущий скролл больше нижней точки статичного оглавления
$('div.fixed-toc').removeClass('hidden'); // делаем фиксированное меню видимым
if (cur_pos == 0) { // если это первый раз,
$('ol.toc_menu').clone().appendTo('div.fixed-toc'); // то в фиксированный блок клонируем и вставляем статичный (можно было сразу в HTML коде прописать 2 меню, одно из которых скрыто, но не хотелось дублировать)
cur_pos = 1; // запомнили, что клонировали, чтобы это больше не повторять
}
for (var j = 0; j < topic_count; j++) { // каждый раз при скроле запускаем цикл
if( (current_scroll < h2[j + 1]) ) { // в котором проверяется положение текущего скрола относительно следующего заголовка. Если заголовок выше, то в фиксированном меню
$('div.fixed-toc span.title').text(h2_title[j]); // указываем заголовок просматриваемого пункта,
$('div.fixed-toc li.active').removeClass('active'); // удаляем выделение активного пункта, если оно есть,
$('div.fixed-toc li').eq(j).addClass('active'); // добавляем выделение к текущему заголовку
break; // выходим из цикла чтобы не перебирать все значения
}
}
} else { // если текущий скролл < положения статичного оглавления, то
$('div.fixed-toc').addClass('hidden'); // фиксированное меню прячем
}
justExecuted = true; //из интернета для оптимизации количества операция при скролле
setTimeout(function() {justExecuted = false;}, 100); //из интернета для оптимизации количества операция при скролле
});