Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #1 (permalink)  
Старый 22.11.2013, 19:04
Аспирант
Отправить личное сообщение для Иззет Посмотреть профиль Найти все сообщения от Иззет
 
Регистрация: 22.11.2013
Сообщений: 39

Jquery viewport - проблема реализации адаптивного меню
Здравствуйте, готовлю сайт-одностраничник - 5 блоков на 100% ширины и высоты и фиксированное меню из якорных ссылок, ведущих к этим блокам. Нужно, чтобы при прокрутке вручную или с помощью меню, при нахождении в каком-либо из 5-и блоков соответствующий пункт меню получал класс "selected". В ходе поисков нашёл плагин jquery viewport и прилагающийся скрипт, но что-то не смог адаптировать под свой сайт:

// add & remove active link
$(document).ready(function() {
$(window).scroll(function () {
var inview = '#' + $("section > article:in-viewport:first").parent().attr('id'),
$link = $('nav a').filter('[hash=' + inview + ']')

if ($link.length && !$link.is('.selected')) {
$('nav a').removeClass('selected');
$link.addClass('selected');
}
})
});

Последний раз редактировалось Иззет, 23.11.2013 в 00:51.
Ответить с цитированием
  #2 (permalink)  
Старый 23.11.2013, 00:41
Аватар для mi.rafaylik
Кандидат Javascript-наук
Отправить личное сообщение для mi.rafaylik Посмотреть профиль Найти все сообщения от mi.rafaylik
 
Регистрация: 07.12.2012
Сообщений: 113

ловить .scroll и проверять совпадение с позицией блоков: http://learn.javascript.ru/play/R6einb

Последний раз редактировалось mi.rafaylik, 23.11.2013 в 04:48.
Ответить с цитированием
  #3 (permalink)  
Старый 23.11.2013, 00:58
Аспирант
Отправить личное сообщение для Иззет Посмотреть профиль Найти все сообщения от Иззет
 
Регистрация: 22.11.2013
Сообщений: 39

По сути нужно, чтобы javascript сравнивал id блока, в кот-ом мы сейчас находимся, с адресом якорной ссылки (в адресе - id блока). И при их совпадении он должен давать класс соответствующей ссылке.
Ответить с цитированием
  #4 (permalink)  
Старый 23.11.2013, 01:53
Аватар для mi.rafaylik
Кандидат Javascript-наук
Отправить личное сообщение для mi.rafaylik Посмотреть профиль Найти все сообщения от mi.rafaylik
 
Регистрация: 07.12.2012
Сообщений: 113

Сообщение от Иззет
сравнивал id блока, в кот-ом мы сейчас находимся с адресом якорной ссылки
Чтоб понять где мы находимся, сначала нужно сравнивать $(document).scrollTop() и $(elements).offset().top
А тогда уже искать в меню соответствующий пункт.

Посмотреть
<div id="nav">
	<a href="one" class="actual">one</a>
	<a href="two">two</a>
	<a href="three">three</a>
</div>

<div class="scroll selected" id="one">one</div>
<div class="scroll" id="two">two</div>
<div class="scroll" id="three">three</div>

$('#nav a').click(function() {
	var id = $(this).attr('href'); // идентификатор блока с нужным якорем
	var y = $('#'+id).offset().top; // координаты начала блока
	$('body').animate({scrollTop:y}, 'slow'); // катимся к якорю + инициируем скроллинг
	return false; // отмена стандартного действия (перехода по ссылке)
});

var lastID; // для id последнего посещённого блока, которому сменили класс
var elemID; // для id текущего блока, которому будем добавлять класс

$(window).scroll(function() {
	var yDoc = $(document).scrollTop(); // координаты текущего скроллинга по вертикали
	$('.scroll').each(function() { // прогуляемся по блокам (надеюсь их немного)
		var yElem = $(this).offset().top; // координаты позиции каждого блока по вертикали
		if (yDoc >= yElem && yDoc < (yElem+50)) { // если верх блока достиг верха страницы + запас 50px
			elemID = $(this).attr('id'); // id блока которому будем добавлять класс
			if (elemID != lastID) { // меняем класс только один раз для текущего блока (а не каждый пиксель скроллинга)
				lastID = elemID; // запоминаем, что здесь класс мы уже добавили
				mark($('#nav a[href='+elemID+']'), $(this)); // смена классов для блока и пункта меню
			}
		}
	});
});

function mark(nav, elem) { // функция смены классов
	$('#nav a').removeClass('actual');
	nav.addClass('actual');
	$('.scroll').removeClass('selected');
	elem.addClass('selected');
}

Последний раз редактировалось mi.rafaylik, 23.11.2013 в 13:03.
Ответить с цитированием
  #5 (permalink)  
Старый 23.11.2013, 13:37
Аспирант
Отправить личное сообщение для Иззет Посмотреть профиль Найти все сообщения от Иззет
 
Регистрация: 22.11.2013
Сообщений: 39

Большое спасибо за помощь, но я что-то затрудняюсь подключить скрипт. Мне на самом деле нужно чтобы только ссылка класс получала, вписал код так:
var lastID; // здесь будем хранить id последнего посещённого блока, которому сменили класс
$(window).scroll(function() {
var yDoc = $(document).scrollTop(); // координаты текущего скроллинга по вертикали
$('.scroll').each(function() { // прогуляемся по блокам (надеюсь их немного)
var yElem = $(this).offset().top; // координаты позиции блока по вертикали
if (yDoc >= yElem && yDoc < (yElem+50)) { // диапазон между верхом блока + запас (если скроллинг быстрый)
var id = $(this).attr('id');
if (id != lastID) { // для каждого блока меняем класс только один раз, нечего повторяться повторяться
lastID = id; // запоминаем, что здесь класс мы уже добавили
mark($('li a[href='+id+']'); // смена классов для блока и пункта меню
}
}
});
});
function mark(nav) { // функция смены классов
$('li a').removeClass('selected');
nav.addClass('selected');
}
может где-то ошибся или какую-то конкретную библиотеку jquery подключить надо ? (все соответствующие классы прописал)

Последний раз редактировалось Иззет, 23.11.2013 в 13:39.
Ответить с цитированием
  #6 (permalink)  
Старый 23.11.2013, 15:54
Аватар для mi.rafaylik
Кандидат Javascript-наук
Отправить личное сообщение для mi.rafaylik Посмотреть профиль Найти все сообщения от mi.rafaylik
 
Регистрация: 07.12.2012
Сообщений: 113

Версия фреймворка в данном случае не важна, скорее всего Ваш html отличается от моего примера.
Обратите внимание на .css в примере. Класс, которым подсвечиваем ссылки в меню, имеет !important

Сначала нужно понять, как работает данная реализация:
1. ловим событие $(window).scroll()
2. на каждой итерацию (каждый пиксель скроллинга) получаем текущую позицию прокрутки документа $(document).scrollTop()
3. на каждой итерации также проверяем, не совпадает ли позиция прокрутки документа с позицией каждого из элементов, но...
4. для этого (если элементов много) проходим по элементам циклом и работаем с каждым
5. для каждого элемента смотрим его положение в документе $(element).offset().top
6. сравниваем наши пункты 2. и 5.: if ($(document).scrollTop() >= $(element).offset().top) {...}
7. но при быстром скроллинге скрипт может не успеть отловить совпадение, поэтому расширяем пункт 6. и добавляем в if (...) вторую границу диапазона (50px от верхней границы элемента): && $(document).scrollTop() < ($(element).offset().top + 50)
8. если условие выполнилось, смотрим id элемента, с которым работаем в данный момент в цикле: $(element).attr('id')
9. используем переменные (lastID, elemID) чтобы лишний раз не добавлять класс ссылке в меню
10. находим в меню ссылку, атрибут которой соответствует id нашего элемента: $('menu a[href='+$(element).attr('id')+']')
11. присваиваем ссылке в меню класс, предварительно убрав класс у остальных ссылок.

Упростил пример: Посмотреть
.

Последний раз редактировалось mi.rafaylik, 23.11.2013 в 19:36.
Ответить с цитированием
  #7 (permalink)  
Старый 23.11.2013, 17:21
Аспирант
Отправить личное сообщение для Иззет Посмотреть профиль Найти все сообщения от Иззет
 
Регистрация: 22.11.2013
Сообщений: 39

Большое спасибо, заработало) только одна проблема - класс ссылкам передаётся только при обратном скроллинге, т.е. снизу вверх, с чем это связано?
Ответить с цитированием
  #8 (permalink)  
Старый 23.11.2013, 18:36
Аватар для mi.rafaylik
Кандидат Javascript-наук
Отправить личное сообщение для mi.rafaylik Посмотреть профиль Найти все сообщения от mi.rafaylik
 
Регистрация: 07.12.2012
Сообщений: 113

Иззет,
Сложно сказать, не увидев Вашего кода.
Покажите всю страницу (html, css, js) в песочнице: http://learn.javascript.ru/play

Последний раз редактировалось mi.rafaylik, 23.11.2013 в 18:59.
Ответить с цитированием
  #9 (permalink)  
Старый 23.11.2013, 18:59
Аспирант
Отправить личное сообщение для Иззет Посмотреть профиль Найти все сообщения от Иззет
 
Регистрация: 22.11.2013
Сообщений: 39

В вашем последнем примере, "Упростил пример: Посмотреть" тоже есть эта проблема, попробуйте вручную прокрутить вниз и, прокручивая сверху вниз, можно увидеть, что ссылке "two" класс "actual" не даётся.
Ответить с цитированием
  #10 (permalink)  
Старый 23.11.2013, 19:24
Аватар для mi.rafaylik
Кандидат Javascript-наук
Отправить личное сообщение для mi.rafaylik Посмотреть профиль Найти все сообщения от mi.rafaylik
 
Регистрация: 07.12.2012
Сообщений: 113

Проверил в Safari, Chrome, Firefox, Opera - работает, каждая ссылка получает свой класс.
К сожалению в IE проверить не могу, т.к. Mac OS X.
Хм... чтоб понять в чём дело, попробуйте:
1. прокручивать медленнее или быстрее.
2. увеличить интервал захвата, не 50 а например 100, возможно, скрипт не успевает совершить проверку при быстром скроллинге.

Последний раз редактировалось mi.rafaylik, 23.11.2013 в 19:40.
Ответить с цитированием
Ответ



Опции темы Искать в теме
Искать в теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
вопрос по реализации 2-х уровнего меню Vempel Общие вопросы Javascript 8 12.08.2012 14:56
Выпадающее меню на jQuery + галерея t_i_m_o_n Элементы интерфейса 3 09.05.2012 22:05
Меню с использованием Jquery, "защита от дурака" :) vyrtime jQuery 2 05.08.2011 12:50
Подправить jQuery меню Pekkonen Работа 1 28.01.2011 08:57
Проблема с меню 856 Общие вопросы Javascript 3 28.07.2008 14:29