Некорректно работает самописный плагин
Всем привет. Заморочился я тут запилить собственный плагин скролла до якоря. Вот один экземпляр скипта на странице работает норм, а два уже некорректно. Не могу понять в чём дело. Окинте, пожалуйста, незамыленным взглядом мой быдлокод и может вы увидите что я проглядел по причине своих скромных знаний 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> |
<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> |
bes,
у меня что-то клики по Div не срабатывают ... и возможно кроме отмены действия по умолчанию, требуется отмена всплытия. |
Цитата:
да, всплытие тоже надо отменить, вешать не на документ и т.п. |
Пасиб, парни. Подкинули "пищи для размышления".
|
Подправил свой плагин. Теперь работает почти так, как нужно. Вот только когда координата срабатывания обработчика (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> |
где [html run и подключённая jquery
|
Цитата:
|
Цитата:
Цитата:
|
Здесь в маленьком окошке ничего не понять. Нужно в отдельном html-файле всё сохранить и запустить. Тогда всё станет понятно. Когда медленно прокручиваешь и середина экрана попадает между блоками div.section, то 2 элемента меню загараются серым. А по-хорошему не должен гореть ни один.
|
Часовой пояс GMT +3, время: 16:40. |