Нюансы употребления плагина jQuery.LocalScroll совместно с CSS-селектором «:target»

  • Tutorial
На HTML-страницах многих сайтов существуют гиперссылки наподобие <a href="#idName">...</a>, которые ведут не на другую страницу, а к некоторому месту на той же сáмой странице, где и ссылка. Это обычное дело для обширных статей с оглавлением (если каждый пункт оглавления является такой гиперссылкою, которая ведёт к названному в нём заголовку) или с примечаниями (если надстрочный знак примечания служит гиперссылкою и ведёт к примечанию в конце текста, а от примечания стоит гиперссылка в обратном направлении). Таких статей немало в сетевых энциклопедиях (вики, например) или в серьёзных сетевых журналах.

К сожалению, переход по такой внутренней гиперссылке в большинстве современных браузеров Паутины совершается мгновенно, ничуть не заметно для читателя. Это совсем не то, что проматывание страницы вручную, которое происходит плавно и занимает некоторое (заметное взору) время, так что даёт читателю некоторое представление об объёме того текста, мимо которого он пролетает.

Досадно, не правда ли?

К счастью, существует плагин для jQuery, который позволяет невозбранно достичь желаемого, то есть без труда обратить всякий переход по внутренней гиперссылке документа именно в такое проматывание, во всём подобное ручному, но только совершаемое автоматически и за достаточно краткое время (по умолчанию — за секунду), так что читатель как раз успевает осознать происходящее и оценить направление проматывания и пройденное расстояние, но ещё не успевает заскучать.

Этот плагин называется jQuery.LocalScroll, и он, окромя jQuery, потребует для своей работы ещё другой плагин (jQuery.ScrollTo), обёрткою для которого является. Так что достаточно установить jQuery и оба эти плагина — и тогда в дальнейшем вызов функции, включающей автоматическое проматывание для всех внутренних гиперссылок, станет можно записывать как нельзя проще:
$($.localScroll());
Вроде бы всё хорошо. Но проблема в том, что по умолчанию такое проматывание является просто проматыванием: документ прокручивается в окне у читателя, и больше ничего.

А ведь, чтобы полностью воссоздать итог перехода по внутренней гиперссылке, необходимо также добавить строку «#idName» к адресу (в строке адреса, учитываемой браузером). Не то слишком уж далеко возвращала бы читателя кнопка «Назад» в браузере: именно ею выразив желание вернуться назад к оглавлению от подраздела (или же от примечания к поясняемому им тексту), читатель неожиданно вернулся бы к предыдущей странице.

Чтобы имитация перехода по внутренней гиперссылке оставалась совершенною, то есть чтобы добавлять строку «#idName» к адресу страницы, Ariel Flesler (автор плагина jQuery.LocalScroll) предлагает включать параметр «hash»:
$($.localScroll({
    hash: true
}));
После этого #-часть адреса действительно переменяется, и кнопка «Назад» начинает работать нормально.

Но достигает ли желаемого совершенства такая имитация перехода по внутренней гиперссылке?

Увы, нет.

Дальнейшие проблемы начинаются, если в стилях документа используется селектор «:target», появившийся в CSS3. Например, стилевое правило *:target { background-color: red } вроде бы должно подсвечивать ту область документа, к которой произошёл переход по внутренней гиперссылке. И в новых браузерах действительно подсвечивает (как гласит MDC, этот селектор поддерживается в Firefox 1.0, в Opera 9.5, в Safari 1.3, и в более новых). Однако, если задействован вызов $($.localScroll()) или $($.localScroll({hash: true})), то в Файерфоксе прокрутка происходит плавно, но CSS-подсветка вырубается. Напрочь.

Что делать?

Я нипочём не догадался бы о причине этого глюка, когда не взглянул бы в исходники плагина LocalScroll нынешней версии (1.2.7).

Оказывается, Ариэль Флеслер решил радикально упростить себе жизнь: вместо того, чтобы дожидаться конца проматывания (и навесить на него такое событие, которое переменяло бы #-часть адреса именно после того, как проматывание полностью завершилось), плагин ещё до проматывания присваивает #-части адреса страницы желаемое значение. Вот так:
location = link.hash;
Просто, не правда ли?

Но ведь такое присваивание автоматически сразу!) прокрутит документ к указанному месту назначения, и тогда вся идея плавного проматывания пойдёт прахом?

Правильно!

И потому, раз уж Ариэль Флеслер решил радикально упростить себе жизнь, то он идёт в своём намерении до конца: его плагин сперва отбирает атрибут «id="idName"» (или «name="idName"») у места назначения гиперссылки, затем создаёт в поле зрения (чтобы исключить прокручивание) новый пустой элемент именно с таким атрибутом, затем присваивает #-части адреса желаемое значение (прокручивание не происходит), затем убивает этот свежесозданный пустой элемент, а месту назначения внутренней гиперссылки возвращает отобранный атрибут — и только тогда начинает спокойно, медленно к нему проматывать.

Файерфокс, разумеется, при этом селектор «:target» применяет именно к новому пустому элементу (который оказывается убит), а гибель этого элемента и дальнейшее появление аналогичного атрибута у другого элемента — игнорирует хладнокровнейше. Я не решил ещё, можно ли считать такое поведение багом Файерфокса. Я также не проверял, как поведут себя Opera, Safari и Chrome в этой ситуации. Мне достаточно и того, что теперь я знаю, как преодолеть это поведение.

Достаточно вызвать $.localScroll() с нормальным человеческим обработчиком, срабатывающим именно после того, как проматывание завершилося:
$.localScroll({
    onAfter: function(target){
        location = '#' + ( target.id || target.name );
    }
});
Вот и всё.

Просто, не правда ли?

Оно всегда так просто, когда всё ужé ясно.

Похожие публикации

AdBlock похитил этот баннер, но баннеры не зубы — отрастут

Подробнее
Реклама

Комментарии 19

    –3
    «позволяет невозбранно достичь желаемого»

    Сергей, как давно мы от Вас не слышали этой фразы, спасибо, порадовали!

    Да, как там Гипертекстовый Векторный? Скоро ли?
      +15
      Скажите, а есть что-нибудь готовое на greesemonkey или подобном, чтобы не видеть посты Мицгола?

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

      А если уж совсем откровенно, товаришь Мицгол, заебал твой дешевый говноэпатаж до крайности. Неужели не понятно, что это неуважительно по отношению к читателям, разговаривать с ними на чужом наречии?! Если же тебе всё это понятно, но ты намеренно не желаешь в публичном месте разговаривать с людьми на нормальном, привычном им языке, — заявляю, пошел ка ты нахуй, Мицгол. Великовозростная ты долбоёбина.

      Минусуйте невозбранно.
        +2
        Экий баттхерт вызывает у вас русский язык.
          +4
          Вы же понимаете, баттхёрт вызван не русским языком. А неуместным его использованием. Мешать IT-тематику и псевдостарый стиль — отнюдь не лучший способ отдать дань традициям. Это во-первых.

          А во-вторых, вот представте, я буду писать хорошие, годные топики, но розовым шрифтом. На голубом фоне. И тут два варианта: либо я 14-летняя девочка, и это мой ограниченный способ самовыражения. И меня можно было бы если не понять, то хотя бы отнестись снисходительно. Мол, со временем пройдёт.

          Но если я взрослый вменяемый человек, переживший этап юношеского максимализма, но продолжающий делать это нарочно, то я никто иной как мудак.

          А в-третьих, вся эта попытка популяризации якобы-тру-русской словесности выглядит как фарс. Сначала смешно, потом не очень. Через какое-то время и вовсе начинает утомлять. Это так же нелепо, как, например, Религиозный Рок. Бугага, которое уже не бугага.

          Я думаю, многие уже уловили послание Мицгола и услышали его точку зрения. Но поскольку употребителей такой лексики (ну хотя бы здесь, на хабре) не стало сильно больше, может стоило бы поумерить свой пыл и перестать уже «нести культуру в массы»?

          Благодарю за внимание.
            –6
            Когда подобных тебе (числом не менее шести, судя по плюсам на твоей реплике) начинает корчить острой изжогою и тошнить нецензурщиною на чужом вам наречии — это явный знак, что я всё делаю правильно, и что я наполовину достиг уж желаемого.
            • НЛО прилетело и опубликовало эту надпись здесь
                –1
                "… И что я наполовину достиг уж желаемого", — то есть еще шесть плюсиков сверху, и мы наконец-то увидим вожделенный «фидофокс»? Ведь верно? Ведь правильно?
                +1
                Хм. Мне кажется, что проблема обстоит в другом совсем. О том, что текст топика воспринимается «превдостарым» или «на чужом наречии» я узнал только из комментариев. Ни малейших затруднений в понимании текста или в его «эпатажности» у меня не возникло.

                Может у ряда людей сложилось некоторая привычка к одному определённому изложению текста, например, из-за постоянного чтения мануалов на техническом английском?
                  –1
                  Вполне адекватный язык изложения у молодца чувака.

                  Если не любо нравиться, не извольте читать сие закрой окно.
                  В конце концов каждый имеет право самовыражаться и изъясняться, как хочет.

                  =-D

                  А в JQuery && plugins и правда порой хитрые глюки можно сыскать, так что благодарствую за рецепты их излечения.
                    +1
                    Очень приятно читать. Не понял, почему комментатор так взъелся на автора. Что то личное?
                    +1
                    Это НЕ русский язык.
                    0
                    действительно, некоторым вместо айтишных статей лучше бы почитать художественную литературу :(
                      +1
                      >> Скажите, а есть что-нибудь готовое на greesemonkey или подобном, чтобы не видеть посты Мицгола?

                      Вот, написал, как упражнение для ума.

                      var a = document.getElementsByClassName('nickname'), div, block;
                      for (var i in a) {
                      block = a[i].parentNode;
                      if (block && block.className.match(/vcard/i) && a[i].href.match(/mithgol/i)) {
                      do {
                      block = block.parentNode;
                      } while (!block || !block.className.match(/hentry/));
                      if (block) {
                      block.style.display = 'none';
                      }
                      }
                      }
                        +1
                        Спасибо, Виктор! =) Обещаю начать использовать сейчас же.
                      0
                      А почему статья не на лубке написана?
                      Жалко, тема хорошая, а читать невозбраможно.
                        +2
                        Суть поста занимает 10% от его текста. Остальное — вода.

                        К сожалению, переход по такой внутренней гиперссылке в большинстве современных браузеров Паутины совершается мгновенно, ничуть не заметно для читателя.
                        К сожалению, пользователь в современных браузерах получает то, что ему нужно сразу. Ну ничего, мы усложним ему жизнь, добавим задержек и тормозной анимации. Но зато, после бесполезного пяляния в монитор в течении трех секунд, пользователь сможет сказать «Вау, сколько текста я пролетел».

                        Тем не менее, плагин не бесполезный, иногда, в редких случаях (а не на каждой странице подряд) переход должен быть именно таким.
                          –2
                          Пишите короче, люди! Пожалуйста!!!
                            +1
                            Автор плагина не так уж и неправ, что Вы поймёте, как только захотите нажать кнопку «назад» после перехода по локальной ссылке. Так-то.
                              –1
                              Я никогда не сомневался, что jQuery-плагины пишут индусы.

                              Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                              Самое читаемое