04.10.2014, 21:26
|
Аспирант
|
|
Регистрация: 24.03.2011
Сообщений: 93
|
|
Некорректно работает самописный плагин
Всем привет. Заморочился я тут запилить собственный плагин скролла до якоря. Вот один экземпляр скипта на странице работает норм, а два уже некорректно. Не могу понять в чём дело. Окинте, пожалуйста, незамыленным взглядом мой быдлокод и может вы увидите что я проглядел по причине своих скромных знаний js.
<head>
<meta charset="utf-8" />
<title>$(selector).waypoint(offset)</title>
<style type="text/css">
html, body, div, ul, li, a, h1 {margin: 0; padding: 0}
a:active, a:focus {outline: 0}
ul {list-style: none}
a, a:visited {color: black}
a:hover, a.active {background: gray}
a:hover, a:active {text-decoration: none}
.navBox {position: fixed; width: 100%; top: 0; background: lightgray}
.nav {text-align: center}
.nav .item {display: inline-block; *display: inline; *zoom: 1}
.nav .ref, .sidebar .ref {display: block; text-decoration: none; font: normal 20px/50px Arial; padding: 0 20px; text-transform: uppercase}
.main {margin-top: 50px}
.section {height: 1000px; border: 1px solid black; margin-top: 20px}
.subSection {height: 500px; margin-top: 461px; border: 1px solid green}
.sidebar {position: fixed; right: 0; background: lightgray}
</style>
<script type="text/javascript" src="jquery-1.10.2.min.js"></script>
<script type="text/javascript">
/**
* Вариант метода waypoint(offset), который перелинковывает все ссылки селектора с якорями.
* $(selector).waypoint(offset);
* Примеры использования.
* $(selector).waypoint('25%');
* $(selector).waypoint('300px');
*/
(function ($)
{
//Декларация метода waypoint.
$.fn.waypoint = function (offset)
{
var refs = this;
this.elems = $('*[id]');
//Помещаем с свойство linx все ссылки, указывающие на элемент.
for (var a = 0; a < this.elems.length; a++)
{
var cur = this.elems[a].id;
if (!this.elems[a].linx || this.elems[a].linx.length == 0)
this.elems[a].linx = this.filter(function (index) { return this.hash == '#' + cur; });
for (var b = 0; b < this.elems[a].linx.length; b++)
{
this.elems[a].linx.eq(b)[0].anchor = this.elems[a];
}
}
//Вешаем анимацию скролла при клике по ссылке.
this.each(function ()
{
$(this).on('click', function (event)
{
event.preventDefault();
var anchor = this.anchor;
$('html, body').animate({ scrollTop: anchor.offsetTop }, 'fast');
});
});
//Если объект offset не передан, устанавливаем значение по умолчанию,
//равное половине высоты окна браузера.
if (!offset) var offset = parseInt($(window).height() / 2, 10);
else
{
//Проценты.
if (offset.search('%') != -1)
offset = parseInt($(window).height() / 100 * parseInt(offset, 10), 10);
//Пиксели.
else if (offset.search('px') != -1)
offset = parseInt(offset, 10);
}
//Обработчик события скролла.
function waypoint(event)
{
//console.log(waypoint.params);
var switchPoint = waypoint.params;
waypoint.elems.each(function ()
{
if (this.offsetTop < $(window).scrollTop() + switchPoint &&
this.offsetTop + $(this).height() > $(window).scrollTop() + switchPoint)
{
waypoint.elems.each(function () { this.linx.removeClass('active'); /*console.log(this.id + ' ' + this.linx[0]);*/ });
this.linx.addClass('active');
console.log(waypoint.params);
}
});
}
waypoint.params = offset;
waypoint.elems = this.elems;
if (!window.scrollHandlers) window.scrollHandlers = [];
window.scrollHandlers.push(waypoint);
if (!window.runScrollHandlers)
{
window.runScrollHandlers = function ()
{
for (var a = 0; a < window.scrollHandlers.length; a++)
window.scrollHandlers[a]();
}
$(window).bind('scroll', window.runScrollHandlers);
}
window.runScrollHandlers();
return this;
}
})(jQuery);
//Использование метода waypoint.
$(function ()
{
$('.nav .ref').waypoint('0px');
$('.sidebar .ref').waypoint('300px');
});
</script>
</head>
<body>
<div class="navBox">
<ul class="nav">
<li class="item"><a class="ref" href="$(selector).waypoint(offset).html#block1">block1</a></li>
<li class="item"><a class="ref" href="$(selector).waypoint(offset).html#block2">block2</a></li>
<li class="item"><a class="ref" href="$(selector).waypoint(offset).html#block3">block3</a></li>
</ul>
</div>
<ul class="sidebar">
<li class="item"><a class="ref" href="$(selector).waypoint(offset).html#Div1">Div1</a></li>
<li class="item"><a class="ref" href="$(selector).waypoint(offset).html#Div2">Div2</a></li>
<li class="item"><a class="ref" href="$(selector).waypoint(offset).html#Div3">Div3</a></li>
</ul>
<div class="main">
<div class="section" id="block1">
<h1>block1</h1>
<div class="subSection" id="Div1">
<h1>Div1</h1>
</div>
</div>
<div class="section" id="block2">
<h1>block2</h1>
<div class="subSection" id="Div2">
<h1>Div2</h1>
</div>
</div>
<div class="section" id="block3">
<h1>block3</h1>
<div class="subSection" id="Div3">
<h1>Div3</h1>
</div>
</div>
</div>
</body>
|
|
05.10.2014, 10:08
|
|
Профессор
|
|
Регистрация: 22.03.2012
Сообщений: 3,744
|
|
<style type="text/css">
html, body, div, ul, li, a, h1 {margin: 0; padding: 0}
a:active, a:focus {outline: 0}
ul {list-style: none}
a, a:visited {color: black}
a:hover, a.active {background: gray}
a:hover, a:active {text-decoration: none}
.navBox {position: fixed; width: 100%; top: 0; background: lightgray}
.nav {text-align: center}
.nav .item {display: inline-block; *display: inline; *zoom: 1}
.nav .ref, .sidebar .ref {display: block; text-decoration: none; font: normal 20px/50px Arial; padding: 0 20px; text-transform: uppercase}
.main {margin-top: 50px}
.section {height: 1000px; border: 1px solid black; margin-top: 20px}
.subSection {height: 500px; margin-top: 461px; border: 1px solid green}
.sidebar {position: fixed; right: 0; background: lightgray}
.section {
padding-top: 60px;
}
</style>
<body>
<div class="navBox">
<ul class="nav">
<li class="item"><a class="ref" href="$(selector).waypoint(offset).html#block1">block1</a></li>
<li class="item"><a class="ref" href="$(selector).waypoint(offset).html#block2">block2</a></li>
<li class="item"><a class="ref" href="$(selector).waypoint(offset).html#block3">block3</a></li>
</ul>
</div>
<ul class="sidebar">
<li class="item"><a class="ref" href="$(selector).waypoint(offset).html#Div1">Div1</a></li>
<li class="item"><a class="ref" href="$(selector).waypoint(offset).html#Div2">Div2</a></li>
<li class="item"><a class="ref" href="$(selector).waypoint(offset).html#Div3">Div3</a></li>
</ul>
<div class="main">
<div class="section" id="block1">
<h1>block1</h1>
<div class="subSection" id="Div1">
<h1>Div1</h1>
</div>
</div>
<div class="section" id="block2">
<h1>block2</h1>
<div class="subSection" id="Div2">
<h1>Div2</h1>
</div>
</div>
<div class="section" id="block3">
<h1>block3</h1>
<div class="subSection" id="Div3">
<h1>Div3</h1>
</div>
</div>
</div>
</body>
<script>
document.addEventListener("click", function (e) {
var target = e.target;
if (target.className == "ref") {
e.preventDefault();
var index = Array.prototype.indexOf.call(document.getElementsByClassName("ref"), target);
document.querySelectorAll(".section")[index].scrollIntoView();
}
});
</script>
|
|
05.10.2014, 10:55
|
|
Профессор
|
|
Регистрация: 27.05.2010
Сообщений: 33,109
|
|
bes,
у меня что-то клики по Div не срабатывают ... и возможно кроме отмены действия по умолчанию, требуется отмена всплытия.
|
|
05.10.2014, 11:52
|
|
Профессор
|
|
Регистрация: 22.03.2012
Сообщений: 3,744
|
|
Сообщение от рони
|
bes,
у меня что-то клики по Div не срабатывают ... и возможно кроме отмены действия по умолчанию, требуется отмена всплытия.
|
ну это просто демонстрация, что есть такой метод scrollIntoView, делалось только для block (только сейчас заметил, что у div тоже <a class="ref" )
да, всплытие тоже надо отменить, вешать не на документ и т.п.
|
|
05.10.2014, 13:42
|
Аспирант
|
|
Регистрация: 24.03.2011
Сообщений: 93
|
|
Пасиб, парни. Подкинули "пищи для размышления".
|
|
18.10.2014, 00:44
|
Аспирант
|
|
Регистрация: 24.03.2011
Сообщений: 93
|
|
Подправил свой плагин. Теперь работает почти так, как нужно. Вот только когда координата срабатывания обработчика (offset) оказывается в промежутке между блоками, класс active имеют два элемента section. Хотя по идее должно быть наоборот: ни один элемент div.section в этот момент не должен иметь класс active. Честное слово даже не знаю куда копать. По умолчанию координата offset - середина окна браузера. Зелёный прямоугольник с правой стороны (div.offset1) в тестовых целях как раз имеет высоту 50%. Опять что-то проглядел что ли?
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<title></title>
<style type="text/css">
html, body, div, ul, li, a, h1 {margin: 0; padding: 0}
a:active, a:focus {outline: 0}
ul {list-style: none}
a, a:visited {color: black}
a:hover, a.active {background: gray}
a:hover, a:active {text-decoration: none}
.navBox, .bottomNavBox {position: fixed; width: 100%; background: lightgray}
.navBox {top: 0}
.bottomNavBox {bottom: 0}
.nav {text-align: center}
.nav .item {display: inline-block; *display: inline; *zoom: 1}
.nav .ref, .sidebar .ref {display: block; text-decoration: none;
font: normal 20px/50px Arial; padding: 0 20px; text-transform: uppercase}
.main {margin-top: 50px}
.section {height: 1000px; border: 1px solid black; margin-bottom: 50px}
.subSection {height: 500px; margin-top: 461px; border: 1px solid green}
.sidebar {position: fixed; right: 0; background: lightgray}
.section {padding-top: 60px}
.offset1 {position: fixed; top: 0; width: 10px; height: 50%; background:
green; z-index: 2}
</style>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script type="text/javascript">
/**
* Вариант метода waypoint(offsetTop), который перелинковывает все ссылки
* селектора с якорями.
* $(selector).waypoint(offsetTop);
* Примеры использования.
* $(selector).waypoint('25%');
* $(selector).waypoint('300px');
*/
(function ($)
{
//Декларация метода waypoint.
$.fn.waypoint = function (offsetTop)
{
var refs = this;
var elems = $('*[id]');
for(var a = 0; a < refs.length; a++)
{
var hash = refs[a].hash.substring(1);
refs[a].anchor = elems.find('*[id=' + hash + ']');
elems.filter('[id=' + hash + ']').each(function()
{
if(!this.refs) this.refs = refs.filter(
function(index){ return this.hash == '#' + hash; });
});
}
//Если объект offsetTop не передан, устанавливаем значение по умолчанию,
//равное половине высоты окна браузера.
if (!offsetTop) var offsetTop = parseInt($(window).height() / 2, 10);
else
{
//Проценты.
if (offsetTop.search('%') != -1)
offsetTop = parseInt($(window).height() / 100 * parseInt(offsetTop, 10), 10);
//Пиксели.
else if (offsetTop.search('px') != -1)
offsetTop = parseInt(offsetTop, 10);
}
//Клик по ссылке инициирует скролл до якорного элемента.
$('body').on('click', function(event)
{
var eventElem = event.target || event.srcElement;
if($(refs).index(eventElem) != -1)
{
event.preventDefault();
refs.removeClass('active');
refs.filter(function (index)
{ return this.hash == eventElem.hash; }).addClass('active');
$('html, body').animate({scrollTop:
$(eventElem.hash).offset().top}, 'fast');
}
});
//Функция присвоения класса active ссылкам на основе данных о положении
//метки offsetTop относительно якорного элемента.
function waypoint(event)
{
event.data.elems.each(function()
{
//Если мета offsetTop находится внутри якорного элемента, то
//добавляем класс active ссылкам с хэшем на этот элемент.
if (this.offsetTop < $(window).scrollTop() + event.data.offsetTop &&
this.offsetTop + $(this).innerHeight() > $(window).scrollTop() + event.data.offsetTop)
{
event.data.refs.removeClass('active');
this.refs.addClass('active');
}
});
}
var data = {
offsetTop: offsetTop,
refs: $(refs),
elems: elems
};
$(window).on('scroll', data, waypoint);
//Инициализация метода.
waypoint({data: data});
return this;
}
})(jQuery);
//Использование метода waypoint.
$(function ()
{
$('.nav .ref').waypoint();
$('.sidebar .ref').waypoint();
});
</script>
</head>
<body>
<div class="offset1"></div>
<div class="navBox">
<ul class="nav">
<li class="item"><a class="ref" href="$(selector).waypoint(offset).html#block1">block1</a></li>
<li class="item"><a class="ref" href="$(selector).waypoint(offset).html#block2">block2</a></li>
<li class="item"><a class="ref" href="$(selector).waypoint(offset).html#block3">block3</a></li>
</ul>
</div>
<ul class="sidebar">
<li class="item"><a class="ref" href="$(selector).waypoint(offset).html#Div1">Div1</a></li>
<li class="item"><a class="ref" href="$(selector).waypoint(offset).html#Div2">Div2</a></li>
<li class="item"><a class="ref" href="$(selector).waypoint(offset).html#Div3">Div3</a></li>
</ul>
<div class="main">
<div class="section" id="block1">
<h1>block1</h1>
<div class="subSection" id="Div1">
<h1>Div1</h1>
</div>
</div>
<div class="section" id="block2">
<h1>block2</h1>
<div class="subSection" id="Div2">
<h1>Div2</h1>
</div>
</div>
<div class="section" id="block3">
<h1>block3</h1>
<div class="subSection" id="Div3">
<h1>Div3</h1>
</div>
</div>
</div>
<div class="bottomNavBox">
<ul class="nav">
<li class="item"><a class="ref" href="$(selector).waypoint(offset).html#block1">block1</a></li>
<li class="item"><a class="ref" href="$(selector).waypoint(offset).html#block2">block2</a></li>
<li class="item"><a class="ref" href="$(selector).waypoint(offset).html#block3">block3</a></li>
</ul>
</div>
</body>
</html>
Последний раз редактировалось ILL-JAH, 26.10.2014 в 14:01.
|
|
18.10.2014, 08:53
|
|
Профессор
|
|
Регистрация: 22.03.2012
Сообщений: 3,744
|
|
где [html run и подключённая jquery
|
|
18.10.2014, 16:13
|
Аспирант
|
|
Регистрация: 24.03.2011
Сообщений: 93
|
|
Сообщение от bes
|
где [html run и подключённая jquery
|
Подключил.
|
|
18.10.2014, 16:52
|
|
Профессор
|
|
Регистрация: 22.03.2012
Сообщений: 3,744
|
|
Сообщение от ILL-JAH
|
Подключил.
|
надо сделать ещё [html run height=800 hide]
Сообщение от ILL-JAH
|
Вот только когда координата срабатывания обработчика (offset) оказывается в промежутке между блоками, класс active имеют два элемента section. Хотя по идее должно быть наоборот: ни один элемент div.section в этот момент не должен иметь класс active. Честное слово даже не знаю куда копать. По умолчанию координата offset - середина окна браузера. Зелёный прямоугольник с правой стороны (div.offset1) в тестовых целях как раз имеет высоту 50%. Опять что-то проглядел что ли?
|
не понял о чём ты и как воспроизвести ситуацию
|
|
18.10.2014, 17:02
|
Аспирант
|
|
Регистрация: 24.03.2011
Сообщений: 93
|
|
Здесь в маленьком окошке ничего не понять. Нужно в отдельном html-файле всё сохранить и запустить. Тогда всё станет понятно. Когда медленно прокручиваешь и середина экрана попадает между блоками div.section, то 2 элемента меню загараются серым. А по-хорошему не должен гореть ни один.
|
|
|
|